Scala #1 | Basic


Introduction

  • Features
    • object-oriented : a pure object-oriented language
    • functional : every function is a value
    • statically typed
    • extensible


1. Expressions

  • Expressions

    • Values val : name the results of expressions

    • Variables var : are like values, except you can re-assigin them.

  • Blocks { }

    • You can combine expressions by surrounding them with {}
  • Functions =>

    • you can define a function that have params
  • Methods def

    • very similar to funtions
  • Classes class

  • Case Classes case class

  • Objects Objects

    • single instances of their own definitions. You can think of them as singletons of their own classes
  • Traits trait

    • abstract data types containing certain fields and methods.
  • Program Entrypoint @main

    • The main method is the entrypoint of Scala program. The JVM requires a main method, named main, that takes one argument : an array of strings

val x = 1 + 1
var x = 1 + 1

// Functions
(x: int) => x + 1
val addOne = (x: Int) => x+1

// Methods
def add(x: Int, y: Int): Int = x + y

// Main, entrypoint
@main def hello() = println("Hello Scala")


2. Operator

  • Arithmetic Operators

    • / : returns Long type
  • Relational Operators

    • == : returns a boolean (checks if the two references point to the same object)

    • === : returns a column in spark, which contains the result of the comparisons of the elements of two columns

    • !=, >, <

  • Logical Operators

    • &&, ||, !
  • Others

    • => : Take LEFT then do RIGHT

      • List(1,2,3).map{ (x:Int) => x*2 } : introduces a function literal, or lambda

      • (A,B) => T: a function that takes parameters of type A[,B...], and returns a value of type T.

      • () => T : Empty parens on the left hand side indicate that the function takes no parameters (also sometimes called a “thunk”);

      • case x => y : In a case clause, they separate the pattern (and optional guard) from the result expression,



3. String

  • String Interpolation : provides a way to use variables inside strings.
    • s-Strings : prepending s to any string literal allows the usage of variables directly in the string
    • f-Strings : prepending f to any string literal allows the creation of simple formatted strings.
    • raw interpolator : The raw interpolator is similart to the s interpolator except that it performs no escaping of literals within the string.

val name = "James"
val age = 30
val height = 1.9d
println(s"$name is $age years old") // "James is 30 years old"
println(f"$name%s is $height%2.2f meters tall")  // "James is 1.90 meters tall"


4. Tuple

  • Fixed-size, heterogeneous container — when you need to return multiple values without defining a case class.
  • Type syntax: (String, Int) is sugar for Tuple2[String, Int]. Scala 2 caps tuples at 22 elements; Scala 3 removes the limit (built on *: and EmptyTuple).
  • Access by 1-based positional accessor: ._1, ._2, …; cleaner via pattern destructuring.
  • Tuple2 has .swap; any tuple can be converted with .toList only if elements share a type.
// construction & positional access
val ingredient: (String, Int) = ("Sugar", 25)
println(ingredient._1) // Sugar
println(ingredient._2) // 25

// destructuring (preferred over ._1/._2)
val (name, qty) = ingredient

// swap (Tuple2 only)
val swapped = ingredient.swap  // (25, "Sugar")

// returning multiple values
def divmod(a: Int, b: Int): (Int, Int) = (a / b, a % b)
val (q, r) = divmod(17, 5)     // q = 3, r = 2

// pattern match
ingredient match {
  case (n, q) if q > 0 => s"$q of $n"
  case _               => "empty"
}

// Scala 3 only: cons-style tuple ops
val t = "a" *: 1 *: true *: EmptyTuple   // (String, Int, Boolean)


5. Types

  • proper types (level-zero): Int, Float, Double, String

    • val company : String = "47 Degrees"
  • First order types (level-one) : List, Option, Either, Map

    • In order to compile, we need to pass a level-zero type to level-one type like :

      • val countries: List[String] = List("ko", "ja", ...)
    • This means that level-one types are generic with a type constructor [_] that takes a proper type or level-zero type

  • Type Constructor [_] : you can consider it as a function that takes a type and returns a type

    • ex) List[_]is just a funtion of type String => List[String]
  • Type Parameter that is itself a type constructor, F[__+] : simply means that F is a type parameter, which is itself a type constructor

    • ex) Let’s say we have a Parser class that takes a level one type.
// we could write something like this:
class Parser[F[_]] {
    def map[A, B](fa: F[A])(f:A => B): F[B]
}

// This means that we could replace F[_] with any level-one type 
// without the F[_] we would have done something like :

class ParserForList {
    def map[A, B](fa: List[A])(f:A => B): List[B]
}

class ParserForOption {
    def map[A, B](fa: Option[A])(f:A => B): Option[B]
}


References