https://www.youtube.com/watch?v=kkTFx3-duc8
Resumen para no gastar una hora viendo el video y para que a mi no se me olvide :)
Choice #1:Infix vs .
items + 10 or item.(10)
xs map f or xs.map(f)
xs flatMap fun filterNot isZero groupBy keyfn or xs.flatMap(fun).filterNot(isZero).groupBy(keyfn)
conclusion: donde haya duda sobre cual es el objecto y cual es el verbo es mejor . (el de la derecha)
Lo que me sugiere que si pensamos en sujetos y verbos seguimos pensando en objecto....no sera facil salir de esa forma de pensar.
Choice #2:Alphabetic vs Symbolic
xs map f or xs *|> f
vector + f or vector.add(f)
(xs.foldLeft(z))(op) or (z /: xs)(op)
UNDEFINED or ???
Odersky recomienda los de la izquierda excepto por el foldLeft donde admite que a el le gusta y le parece mas claro el de la derecha que es como un domino que va de izq a derecha pero admite que la mayor parte de la gente no entiende esta simbologia y que por lo mismo quiza no sea la mejor solucion.
Choice #3:Loop, recursion or combinations?
xs map f
or
var buf = new ListBuffer[String]
for (x <- xs) buf += f(x)
xs.toList
or
def recurs(xs: List[String]) = xs match {
case x :: xs1 => f(x) :: recur(xs1)
case Nil => Nil
}
No comment....
xs.grouped(2).toList.map {
case List(x,y) = > x*y
}
or
var buf = new ListBuffer[Int]
var ys = xs
while (ys.nonEmpty){
guf += ys(0)*ys(1)
ys = ys.tail.tail
}
or
def recur(xs: List[Int]): List[Int] = xs match {
case x1 :: x2 :: xs1 => (x1 * x2) :: recur(xs1)
case Nil => Nil
}
recur(xs)
Combinators: Easiest to use
Recursive functions: bedrock of FP
Pattern matching: Much clearer and safer than test and selections
Loops: Because they are familiar, and sometimes are the simples solution
Recomendations:
1. Consider using combinators first
2. if this becomes too tedious, or efficiency is a big concern, fall back on tail-recursive functions.
3. Loops can be use in simple cases, or when the computation inherently modifies state.
Choice #4: Procedures or "="
def swap[T](arr: Array[T], i: Int, j: Int){
val t = arr(i);ar(i) = arr(j);arr(j) = t
}
def swap[T](arr: Array[T], i:Int, j:Int): Unit = {
val t = arr(i);arr(i) = arr(j); arr(j) = t
}
Scala accident ??
Choice #5: Private vs nested
def outer(owner: Symbol) = {
def isJava(sym: symbol): Boolean = sym hasFlag JAVA
if (symbols exists isJava)
}
easy nested almost always you can avoid passing parameters from the enviroment. But if you not capturing nothing code is harder to read.
def isJava(sym: symbol): Boolean = sym hasFlag JAVA
if (symbols exists isJava)
}
Choice #6: Pattern matching vs dynamic dispatch
class Shape
def area: Double
case class Circle(centre: Point, radius: Double) extends Shape
def area = pi * radius * radius
case class Rectangle(ll: Point, ur: Point)
def area = (ur.x - ll.x)* (ur.y - ll.y)
or
def area(s: Shape): Double = s match {
case Circle(_, r) => math.pi*r*r
case Rectangle(ll,ur) => (ur.x - ll.x)* (ur.y - ll.y)
...
}
Un espectador pregunta: Y que pasa cuando uno se olvida de definir el metodo para uno de las clases?
Hay algo que se llama sealed classes