- Named functions
def foo(x:Int): Int = x + 1
def foo(x:Int): Int = {
x + 1
}
- Anonymous functions
(x: Int) => x + 1
- Partial application
def add(a:Int, b:Int): Int = a + b
val add3 = add(1, _)
add3(2)
// res: Int = 5
_ acts as a an unnamed magical wildcard and has different meanings regarding the context
- Curried functions
def multiply(a: Int)(b: Int): Int = a * b
val foo = multiply(3) _
foo(2)
// res: Int = 6
Making a function curried :
def multiply(a: Int, b: Int): Int = a * b
val curriedMultiply = (multiply _).curried
val foo = curriedMultiply(2)
foo(3)
// res: Int = 6
- Constructor
It's basically code outside of method definitions in class.
class Cat(sex: String) {
val name: String = if (sex == "male") {
"pompon"
} else if (sex == "female") {
"pomponette"
} else {
"giroflée"
}
}
val cat = new Cat("female")
cat.name
// res: String = pomponette
If you need a constructor parameter, use an abstract class. Abstract class constructors can take parameters; trait constructors can’t.
Btw a trait is basically the same as an abstract class, you can't implement methods in it. Nevertheless it's preferable to use traits since many of them they can be extended by a given class.
Used to prevent from using new
keyword when instantiating a class :
class Foo {}
object FooCompanion {
def apply() = new Foo
}
val newFoo = FooCompanion()
// res: Foo
- Basics
val times = 1
times match {
case 1 => "one"
case 2 => "two"
case _ => "fuck it"
}
times match {
case i: Int if i == 1 => "one"
case i: Int if i == 2 => "two"
case _ => "fuck it"
}
Notice: the type : Int
isn't mandatory here and can differ if matching different types
- Case classes
Case classes are used to conveniently store and match on the contents of a class. You can construct them without using new.
case class Cat(sex: String, breed: String)
val kitty = Cat("female", "maine coon")
New pattern matching with case class:
def catProbableName(cat: Cat) = cat match {
case Cat("female", "maine coon") => "pomponette"
case _ => "IDK"
}
- Array:
val numbers = Array(1, 1, 2, 3)
- List:
val numbers = List(1, 1, 2, 3)
They are immutable - Set:
val numbers = Set(1, 1, 2, 3)
res: Set[Int] = Set(1, 2, 3)
- Tuple:
val hostPort = ("localhost", 80)
res: hostPort = (String, Int)
They can also be defined this way :1 -> 2
(Int, Int) = (1, 2)
- Map: `Map("foo" -> "bar")
map
exact as a lodash _.each and returns smth:
val numbers = List(1, 2, 3, 4)
numbers.map((i: Int) => i * 2)
//res: List[Int] = List(2, 4, 6, 8)
- foreach returns nothing
flatten
:
List(List(1, 2), List(3, 4)).flatten
//res0: List[Int] = List(1, 2, 3, 4)
flatMap
:nestedNumbers.flatMap(x => x.map(_ * 2))