Listas por comprensión- Comparamos las listas por comprensión con el uso de filter y map y vemos que la función
nombresDeAlumnosQueAprobaron = map nombre . filter aprobo
puede también escribirse como una lista por comprensión:
nombresDeAlumnosQueAprobaron alumnos = [nombre alumno | alumno <- alumnos, aprobo alumno]
- Una diferencia que podemos notar entre ambas definiciones es la cantidad de parÔmetros a la izquierda del igual, en el segundo caso hay uno, mientras que en el primero no hay. ¿Por qué pasa eso?
Eso pasa porque
map nombre . filter aprobo
es una función ya que es la composición de dos funciones.
En cambio
[nombre alumno | alumno <- alumnos, aprobo alumno]
es una lista, esa es una diferencia importante y es un criterio que nos va a permitir saber cuÔndo nos conviene usar map y filter en lugar de listas por comprensión.
- Otra cosa que agregan las listas por comprensión es la posibilidad de hacer pattern matching:
[nombre | (nombre, nota) <- alumnos, nota > 4]
- Otro ejemplo si tengo una lista de remeras de la forma:
modelos = [("GoodIdeaBadIdea", "flex", 2, "negro"), ...]
a partir de esa lista podemos construir otra usando listas por comprensión y pattern matching:
[(nombre, color) | (nombre, _, cant, color) <- modelos, cant > 2]
Aquà se puede ver la verdadera potencia de las listas por comprensión vs. map y filter, la posibilidad de utilizar el pattern matching.
- En resumen:
- Las listas por comprensión nos dan funcionalidades similares a las del map y filter, entonces es probable que en muchas situaciones se presenten como soluciones alternativas a un mismo problema.
- Las listas por comprensión permiten aprovechar mejor el pattern matching, entonces en los casos donde pueda usar esa caracterĆstica probablemente sea mĆ”s piola usar listas por comprensión en lugar de map y filter.
- Con listas por comprensión yo siempre defino una lista, mientras que combinando map y filter con aplicación parcial yo puedo definir funciones, eso los hace mÔs aptos para la composición, por lo tanto en los casos en que yo necesite componer (o trabajar al nivel de función por cualquier otro motivo, puede resultar mÔs adecuado usar map, filter, aplicación parcial, composición, etc.
Definiciones Locales- Si tengo una función muy particular que sólo voy a utilizar en un contexto particular, podemos definir la función localmente, usando la forma where.
- Ejemplo:
f = map nombreYColor . filter ((>2).cantColores)
Ā Ā Ā Ā where nombreYColor remera = (nombre remera, color remera)
Expresiones lambda- Una forma alternativa a lo anterior es evitar incluso ponerle nombre, podemos evitar la parte izquierda de la definición.
- Esta herramienta la denominamos expresión lambda, y se puede usar de la siguiente manera:
f = map nombreYColor . filter (\remera -> cantColores remera > 2)
- O incluso:
f = map (\remera -> nombre remera, color remera) . filter (\remera -> cantColores remera > 2)
Este segundo caso es mÔs poderoso, ya que esa función no se puede definir utilzando aplicación parcial y composición.
EjercitaciónA partir de esta información: modelos = [("GoodIdeaBadIdea", "flex", 2, "negro"), ...] pedido = [("Mariana", [("GoodIdeabadIdea", "S"), ("Animaniacs", "S")], ("Nico", [("Solong", "M"), ...])] precio (_, "flex", cant, _) = 50 + cant precio (_, _, _, _) = 60
nombreModelo (modelo, material, cantidadDisponible, color) = modelo colorModelo (modelo, material, cantidadDisponible, color) = color
nombreRemeraPedida (nombre, cantidad) = nombre
Vamos a tratar de resolver los siguientes requerimientos: |