blog de bferro

Scala: Clases "case" y pattern matching (1/2)

Las clases case (no encuentro un término adecuado en español) son uno de los mecanismos que Scala utiliza para hacer "pattern matching" sobre objetos, sin la necesidad de escribir el código de boilerplate que se requeriría si esta opción no existiera.
Pattern matching es una necesidad en la programación, y en el caso particular de la programación funcional es una técnica natural para resolver muchos problemas que hacen uso de datos recursivos con estructuras arbóreas.
Scala contribuye al pattern matching sobre objetos tratando de lograr cierta uniformidad de la sintaxis funcional y la sintaxis orientada a objetos.
Para describir las clases case y su utilización en el pattern matching necesitamos también hablar de otras cosas como las clases sealed (selladas) y del tipo Option y sus "derivados".
Utilizo aquí los ejemplos del texto de Odersky. Es un caso de estudio sencillo de comprender, y así no se pierde el tiempo. No veo necesario inventarme otros ejemplos.

Veamos primero las clases case

Las patentes de Steve Jobs

Las patentes del mago Jobs, considerado como uno de los grandes inventores de este mundo.
http://www.nytimes.com/interactive/2011/08/24/technology/steve-jobs-pate...

Los niveles de "expertisidad" en Scala

En http://www.scala-lang.org/node/8610, Martin Odersky escribe sobre los niveles de Scala para el principiante y el experto. Me parece interesante "copiar" aquí una parte referente a lo que debe conocerse y usarse según el nivel y el tipo de cosas que desarrollamos. Esto creo que puede orientar a los que están en "amoríos"con este lenguaje.

Level A1: Beginning application programmer
Java-like statements and expressions: standard operators, method calls, conditionals, loops, try/catch
class, object, def, val, var, import, package
Infix notation for method calls
Simple closures
Collections with map, filter, etc
for-expressions

Level A2: Intermediate application programmer
Pattern matching
Trait composition
Recursion, in particular tail recursion
XML literals

Level A3: Expert application programmer
Folds, i.e. methods such as foldLeft, foldRight
Streams and other lazy data structures
Actors
Combinator parsers

Level L1: Junior library designer
Type parameters
Traits
Lazy vals
Control abstraction, currying
By-name parameters

Level L2: Senior library designer

Scala: Parte 2

Los primeros pasos en Scala
Como había comentado en mi post anterior sobre el lenguaje Scala, mi pretensión es contribuir "paso a paso" con algunas de las cosas importantes de este lenguaje, discutiendo conceptos relevantes y algo de código para ilustrar esos conceptos.
Creo que es necesario aprender a caminar con pasos firmes para después correr, y por esa razón me voy despacio explicando cada cosa en su momento.
Casi todos los libros y tutoriales de Scala aconsejan comenzar con el intérprete de Scala y "oyendo" a los que saben voy a hacer lo mismo, aunque también me gustaría "saltar del REPL a programas completos. Esa forma me ha ayudado a entender el lenguaje, aunque debo confesar que aun me falta mucho por aprender y que bueno que sea así pues evito el aburrimiento.
El REPL (Read Eval Print Loop) es un shell interactivo que compila código de Scala y retorna el resultado (o el tipo) de manera inmediata. Espero que todos los que leen esto ya tengan en su máquina a Scala y puedan interactuar con el intérprete a medida que leen esta notas.
Definamos algunas variables en el REPL:

scala>val mensaje = "Hola Java Mexico"

Scala: Parte 1

En este sitio se han discutido algunas de las cosas del lenguaje Scala, todas ellas muy interesantes y que han llamado la atención de los participantes en esta comunidad.

Tengo la intención de escribir varios artículos sobre este lenguaje de manera “disciplinada” lo que quiere decir comenzar desde el principio, aunque seguramente repetiré algunas de las cosas que ya se han dicho aquí. Eso no es traumático: a veces conviene leer lo que varios dicen sobre lo mismo.

Seguramente va a suceder que los posts queden “algo” extensos: pongo el parche antes que salga el grano, aceptando cualquier crítica al respecto y a otras cosas que pueda escribir aquí.

Comienzo entonces con una introducción al lenguaje. Para algunos será “pan comido” para otros será carbohidrato por digerir.

Scala es un lenguaje escalable
Scala es bautizado con ese nombre para precisamente decir que se inventa un lenguaje escalable.

El cálculo lambda y el Ceylon de G.King

Al leer la presentación de G. King del futuro lenguaje Ceylon, al que @domix hizo referencia en estos días en este sitio, me sorprendió como a muchos otros en la red, la forma tan "poco agradable" que G. King se refirió al cálculo lambda, tomando en cuenta la importancia de ese concepto en la computación, y también tomando en cuenta el background matemático del autor.
Gavin King en su blog ayer se refirió a ese "missunderstanding" en la blogosfera y escribió una aclaración (sin olvidar su ego) que vale la pena leer. Ahí se los dejo:

Ceylon presentation: a clarification. http://in.relation.to/Bloggers/CeylonPresentationAClarification

Bien valdría la pena

Creo que vale mucho la pena leer y discutir este blog entry: http://chaosinmotion.com/blog/?p=622

Reglas de Reflexión != Reglas de No Reflexión

Lo que el compilador de Java conoce es diferente de lo que conoce el run time.
Esa diferencia se debe a varias cosas, entre ellas al “desconocimiento” que la máquina virtual tiene de “cosas” que el compilador sí conoce.
En ocasiones suceden cosas “extrañas”.
Es el caso de algunas diferencias importantes entre el código “normal” y el código que hace uso de reflexión.

A continuación algunos ejemplos de algunas de esas diferencias.

Ejemplo 1
La firma (signature) de los constructores de las clases inner son “distintas” para el compilador y para el run time. La máquina virtual “no sabe nada de clases inner”. La unidad de distribución de código en Java es la clase.

El código:

package innerclasses;

import java.lang.reflect.Constructor;
import static java.lang.System.out;

//La clase pública Main
public class Main {

  public static void main(String[] args) throws Exception {
   
    //Creamos un objeto de clase Outer
    Outer outerObject = new Outer();
   
    //Obtenemos los objetos Class que describen a las clases
    //Inner y Nested definidas dentro de Outer
    Class innerClass = outerObject.getInnerClass();

Effective Java: Debatiendo conceptos

En uno de los hilos de discusión de este Foro, se comentaba sobre algunos libros para adentrarse más en buenos principios de diseño, y surgió el libro de Joshua B. "Effective Java".

Pensé que a lo mejor y resulta útil comentar sobre los Items que se discuten en ese texto y seleccioné para empezar el 16.
Es un principio de diseño muy comentado en la literatura. El libro de GOF también lo discute, y varios APIs del JDK hacen buen uso y también mal uso de él.

¿Quien empieza?

Item 16: Favor composition over inheritance

A propósito de la declaración explícita de tipos y su comprobación en tiempo de compilación

En discusiones recientes en este sitio se ha hablado mucho de los lenguajes tipados y no tipados y la mezcla de ambas técnicas en algunos lenguajes, y me acordé de un ejemplo de Joshua Bloch en su libro Effective Java que, aunque simple es muy ilustrativo.

Java, como sabemos, es un lenguaje "estricto" en tipos. Escribo entre comillas la palabra estricto para no meterme en broncas con la teoría de tipos. Lo que pretende Java y otros lenguajes es evitar al "máximo" (otra vez las comillas por la misma razón) los errores en ejecución por la incompatibilidad de tipos.

Joshua Bloch se pregunta entonces

por qué definir

  1.  java.io.ObjectOutput.writeObject(Object obj)
  2.  

cuando realmente debe ser

  1.  java.io.ObjectOutput.writeObject(Serializable obj)
  2.  

Errores sencillos que ilustran conceptos importantes.

Distribuir contenido