A continuación presentamos algunas de las principales características del código Scala:
1.Compose
En Scala todo es una expresión, entonces, todo se puede combinar con todo
1 2 3 4 5 6 7 8 9 | if ( age >= 18 ) “ grownup” else “minor” val result = tag match { case “email” => try getEmail() catch handleException case “postal” => scanLetter() } |
2. Match
Datos que se descomponen por coincidencia de patrones. Es el dual de la composición
1 2 3 4 5 6 7 8 | trait Expr case class Numer( n: Int) extends Expr case class Plus (l: Expr, r: Expr) extends Expr def eval( e: Expr): Int = e.match{ case Numer(n) => n case Plus(l, r ) => eval (1) + eval(r) } |
Simple y flexible, incluso si es muy verboso.
Si lo coidificamos en el modo de Orientación a Objetos tradicional:
1 2 3 4 5 6 7 8 9 | trait Expr{ def eval: Int } case class Number(n:Int) extends Expr{ def eval: n } case class Plus(l: Expr, r: Expr ) extends Expr { def eval = l.eval + r.eval } |
Se presenta adecuado si las operaciones son pocas, pero mezcla modelo de datos con reglas de negocio.
3. Agrupar
En Scala todo puede ser agrupado y anidado
Se debe tener una disciplina de alcance para los tipos static
Dos nombres de espacios: Terms y Types, las mismas reglas para ambos
1 2 3 4 5 | def solutions (target: Int) : Stream[Path] = { def isSolution (path: Path) = path.endState.contains(target) allPaths.filter(isSolution) } |
Tip: No ponga mucho en una expresión
1 2 3 4 5 | jp.getRawClassPath.filter( _.getEntryKind == IClasspathEntry.CPE_SOURCE). Iterator.flatMap( entry => flatten(ResourcesPlugin.getWorspace. getRoot.findMember(entry.getPath))) |
Es increíble lo que se puede hacer en una sola sentencia, pero esto no significa que lo deba hacer. ( Por favor, no haga esto J )
Tip: encuentra nombres con significado
Existe un gran valor en nombres con significado, y si no le es fácil agregar un significado, puede ser un indicador de que algo no está bien.
1 2 3 4 5 6 7 | val sources = jp.getRawClassPath.filter(_.getEntryKind == IClasspathEntry.CPE_SOURCE) def workspaceRoot = ResourcesPlugin.getWorkspace.getRoot def filesOfEntry (entry: Set[File]) = flatten(workspaceRoot.findMember(engry.getPath) sources.iterator flatMap filesOfEntry |
4. Recursividad
Es mejor que un bucle y el manejo de la cola de recursividad es eficiente. Es más rápido que un bucle.
1 2 3 4 | @tailrec def sameLength( xs : List [T] , ys: List[U]) : Boolean if (xs.isEmpty) ys.isEmpty else ys.nonEmpty && sameLength(xs.tail , ys.tail) |
5. Abstracción
Las funciones son expresiones abstractas.
Las funciones en si son valores
Pueden tener nombre o ser anónimas
1 2 3 | def isMinor(p: Person) = p.age < 18 val (minors, adults) = people.partition(isMinor) val infants = minors.filter( _.age <= 3 ) |