Traversable ops – Fold

Esta es la primera de una serie de entradas relacionadas con las operaciones más comunes en el mundo de la programación funcional con Scala: las operaciones pertenecientes a la API de Traversable.

Traversable se considera la base para todas las colecciones de Scala y se caracteriza principalmente por dos rasgos:

  • Strictness: Todos los elementos tienen que ser computados previamente para poder manejarlos como valores.
  • Orderness: Los elementos mantienen una relación de orden entre ellos

Hay otro tipo de colecciones como los Streams, de evaluación perezosa, pero no perdamos el foco. Hoy hablaremos sobre el fold…sin ponernos nerviosos, ni colapsar.

nlY1Wxv

Supongamos que queremos concatenar los números del 1 al 5 en una cadena de texto, obteniendo el resultado “My numbers are: 12345”, ¿cuál sería la primera aproximación? Podría ser algo del estilo

var initial: String = "My numbers are: "
for(i <- 1 to 10){
  initial = initial + i.toString
}

Funcionaría. Pero os podéis imaginar lo feas que quedan las variables.

40HYLZX

No os preocupéis. La operación que os proponemos para sustituir el bucle anterior es fold, que tiene dos variantes: foldLeft y foldRight. Mientras que la primera operación ejecuta elemento a elemento del Traversable de manera iterativa, la segunda lo hace de manera recursiva, por tanto se recomienda evitarla si la colección sobre la que ejecutamos el foldRight tiene un tamaño considerable. Nos centraremos pues en la primera operación.

La notación del foldLeft para un cierto Traversable[T] es

def foldLeft[U](zero: U)(f: (U,T) => U): U

dicho así puede parecer dificil de ver. Apliquemos la operación al ejemplo anterior:

El elemento ‘zero’ en este caso, sería la cadena inicial de tipo String “My numbers are: ”
Y la función a aplicar para cada par de String, Int sería la concatenación.

Por tanto seríamos capaz de expresar el primer snippet de código, sin hacer uso de variables, de la siguiente forma:

(1 to 5).foldLeft("My numbers are: ")(
  (accumulator,iterator) => accumulator + iterator.toString)

Para aquellos que creais que esta sintaxis es demasiado mainstream, hay una notación alternativa que permite realizar la misma operación de la siguiente forma:

("My numbers are: " /: (1 to 5))((accumulator,iterator) =>
  accumulator + iterator.toString)

Fácil, sencillo y para toda la familia 🙂

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s