¡Esta es una revisión vieja del documento!
−Tabla de Contenidos
Repaso de Programación Funcional, Divide y Vencerás
Comparación de patrones
ordena (x,y), ordena :: (Int,Int) → (Int,Int) que, dados dos enteros, los ordena de menor a mayor.
ambospositivos x y, ambospositivos :: Int → Int → Bool, que dados dos enteros devuelve True si los dos son positivos.
edad :: (Int, Int, Int) → (Int, Int, Int) → Int que dadas dos fechas indica los años transcurridos entre ellas. Por ejemplo edad (20,10,1968) (30,4,1987) = 18.
Suponer (o comprobar con un módulo o definición local!!!!) que las fechas están siempre bien formadas y que la primera es menor o igual a la segunda.
cabeza xs, cabeza :: [a] –> a, que devuelve el primer elemento de una lista.
cola xs, cola :: [a] –> [a], que devuelve toda la lista menos el primer elemento.
esVaciaOPrimer0 xs, esVaciaOPrimer0 :: [Int] → Bool que dada una lista xs decida si xs es vacía o bien su primer elemento es 0.
segundoEsSegundo (x,y) zs, segundoEsSegundo :: (Int,Int) → [Int] → Bool que dada una tupla de enteros (x,y) y una lista de enteros zs comprueba si el segundo elemento de la tupla es igual al segundo elemento de la lista.
recortaDia xs, recortaDia :: [Char] → [Char] que dada una lista de caracteres xs, comprueba si las letras de la lista forman el nombre de un día de la semana, si es así, si el día no es del fin de semana, devuelven la primera letra solamente, en cambio, si el día es de fin de semana, devuelven el nombre del día completo. Ayuda: fíjense que el resultado siempre debe ser una lista de caracteres!
Modularización
Para hacer un programa que resuelva un problema complejo, lo mejor es analizar bien el problema para dividirlo en partes más chicas. Solucionaremos estas partes más chicas cada una por separado, comprobando que efectivamente cada una hace lo que esperamos que haga. Finalmente, las uniremos para llevar a cabo la tarea compleja que nos planteábamos al principio. A esta estrategia se la conoce como modularización, ya que cada una de las partes en las que se divide el problema se llama módulo o subrutina, pero informalmente también se conoce como “divide y vencerás”, ya que lo que hacemos es parecido a dividir un ejército muy numeroso en partes más pequeñas para vencerlas a cada una por separado.
Definiciones locales
A veces queremos modularizar pero queremos que los módulos sólo estén disponibles para el programa que estamos haciendo en este momento, y no para todo el resto. Por ejemplo, si queremos definir la función “cola
” de forma distinta a como se define normalmente, porque lo necesitamos para ese programa en concreto.
Podemos definir módulos (en el caso de haskell, funciones) de forma que sólo las pueda usar un determinado programa, definiéndolas localmente. Vimos un ejemplo de esto en la clase anterior, para definir la función que calcula el área de un prisma:
area :: Int -> Int -> Int -> Int area alto ancho fondo = 2*frente + 2*lado + 2*tapa where frente = alto * ancho lado = alto * fondo tapa = ancho * fondo
En este ejemplo hemos definido localmente las funciones frente
, lado
y tapa
. Eso quiere decir que si tratamos de usarlas fuera de esta función, el intérprete nos dirá que no las conoce, o aplicará otras funciones con el mismo nombre pero definidas en otro lugar. En cambio, cuando usemos la función area
, vamos a usar las definiciones que hemos definido localmente. Las variables definidas en la definición que contiene las definiciones globales siguen manteniendo su referencia en las definiciones locales. En este caso, las funciones frente
, lado
y tapa
usan las variables alto
, ancho
y fondo
como si estuviéramos en la función area
, porque de hecho estamos definiendo cosas dentro en la función area
.
Para definir funciones locales a otra función, usamos la palabra clave where
y el espacio horizontal y vertical: las definiciones locales (y la palabra clave where
) tienen que estar como mínimo un espacio más a la derecha que la función dentro de la cual se definen, y no pueden estar separadas por una línea en blanco. Veamos qué pasa cuando no respetamos estas normas de sintaxis? Veamos por ejemplo si no respetamos el espacio horizontal:
area a b c = 2*frente + 2*lado + 2*tapa where frente = a*b lado = b*c tapa = a*c
El intérprete va a entender que las funciones frente
, lado
y tapa
son independientes de area
, por lo tanto no va a entender que la variable b
es la misma que la de la definición de area
.
Main> :e ERROR "1.hs":69 - Undefined variable "b"
Funciones locales vs. globales