Los 7 pecados capitales de las expresiones lambda

Hace unas semanas estuvimos hablando de expresiones lambda. Vimos como utilizarlas y algunas de las ventajas que ofrecen.

Sin embargo, no es oro todo lo que parece. El pasado mes de Abril, Jamie Allen vino al meetup de Scala en Madrid y nos habló del lado oscuro de las expresiones lambda: “What you need to know about lambdas”. En este post vamos a hacer un overview de la charla, y corroborar que no podemos usar expresiones lambda de cualquier manera.

Primer problema: No es reutilizable

Debido a que no estamos poniendo nombre a la función, no podremos reutilizarla en otros lugares.

Segundo problema: No se puede testear de forma aislada

Como es una función implementada de forma ad-hoc, e incrustada en algún lugar, no es posible probarla de forma aislada.

Tercer problema: Mantenimiento

No es bueno abusar de expresiones lambda complicadas y anidadas. Provoca que nuestro código se vuelva dificil de seguir, y por tanto, poco mantenible.

List(1, 2, 0, 3, 4).flatMap(
  x => (1 to x).filter(
    _ % 2 == 0
  ).map( _ * 2 )
)

//List(4, 4, 4, 8)

Cuarto problema: trazas de error

Este problema varía en función del lenguaje de programación que se utilice. En algunos casos las trazas de error serán mejores y en otros casos te darán ganas de cortarte las venas. En nuestro caso, en Scala, cuando aparece un error en una función anónima obtendremos un mensaje de error con esta pinta:

List(1, 2, 0, 3, 4).map(1 / _)

java.lang.ArithmeticException: / by zero
at $anonfun$1.apply$mcII$sp(<console>:8)
at $anonfun$1.apply(<console>:8)
at $anonfun$1.apply(<console>:8)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
at scala.collection.immutable.List.foreach(List.scala:318)
...

Debido a que no se ha dado nombre a la función, el sistema nos devolverá un error en un $$anonfun. Un poco WTF.

Quinto problema: Dificultad para depurar

Realmente no es un problema propio de las expresiones lambda, sino de la forma de expresar el código.
Si encadenamos varias expresiones lambda en la misma línea y existe algún error en alguna de ellas, no podremos saber cual de ellas ha fallado. Por ello es conveniente separarlas en varias líneas.

La expresión

List(1, 2, 0, 3, 4).map(_ + 1).filter(_ % 2 == 0).map(_ * 2)

será mejor expresarla de esta forma:

List(1, 2, 0, 3, 4).map(_ + 1)
  .filter(_ % 2 == 0)
  .map(_ * 2)

Sexto problema: Puede encapsular variables con estado

Una función lambda puede tener acceso a todo el estado de su scope. Por tanto, puede tener acceso a algún valor mutable y hacer que tengamos diferentes resultados en cada ejecución. Algo que no queremos en la programación funcional.

Séptimo problema …

Sus problemas se pueden encapsular en solo seis y provocan que algunos títulos de post no encajen del todo.

desk_flip

Conclusión

Como hemos podido ver, usar expresiones lambda puede originar algunos quebraderos de cabeza. Por ello se recomienda usar solo aquellas que tengan una baja complejidad. En caso de que queramos hacer algo más complejo o enrrevesado será mejor definir un método para poder testearla y depurarla sin ningún tipo de problema. Además, hay que tener especial cuidado de no utilizar variables del scope que puedan cambiar de valor. Debemos seguir un enfoque funcional.

Os recomiendo que le echéis un ojo a la charla . En ella se profundiza mucho más (este post solo ha sido un pequeño resumen) y puede ayudarnos a trabajar con expresiones lambda de una mejor forma.

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