martes, 10 de junio de 2008

Por qué escribir de manera inversa?

Estos días de "reposo" que tuve que hacer, los aproveché para ver algunos videos de Abelson y Sussman que son realmente muy recomendables.
Ellos hacen mucho hincapié en los mimos principios que usamos nosotros en POO y DAO, es muy interesante ver como piensan en el MIT y como lo hacían hace más de 20 años atrás!
Sin embargo, viendo uno de los ejemplos que mostraban me di cuenta que no siempre uno cumple lo que dice. Por ejemplo, vean este código:


Más allá de que es un poco difícil de entender la sintaxis porque está escrito en Scheme, lo que quiero remarcar es que para entender lo que hace hay que leer de abajo para arriba. La idea es que esta función sume los primeros n fibonaccies que son impares, y para ello utiliza el patrón
map/filter. Se debe leer, como dije, de abajo para arriba:
1) enum-interval 1 n -> crea un intervalo de 1 a n (a)
2) map fib (a) -> mapea los números del intervalo a su fibonacci correspondiente (b)
3) filter odd (b) -> filtra aquellos fibonacci que son pares, o sea, se queda con los impares (c)
4) accumulate cons '() (c) -> Acumula los resultados en una lista usando un lista vacía como valor inicial
Ahora, si estamos abogando por escribir código entendible, que se pueda leer fácilmente, etc. por qué para leer esta función tengo que hacerlo de abajo para arriba en vez de arriba para abajo que es más natural?
Me parece que sería mejor algo así (ahora en Smalltalk):

interval := 1 to: n.
fibonacciNumbers := interval collect: [ :aNumber | aNumber fibonacci ].
oddFibonacciNumbers := interval select: [ :aNumber | aNumber odd ].
^oddFibonacciNumbers

Al hacerlo así, se puede leer de manera natural, de arriba hacia abajo, de izquierda a derecha como van realizándose el computo.
Tiene una desventaja implementativa respecto de la primera versión y es que guarda todos los fibonacci para luego filtrarlo para quedarse con los impares mientras que la versión Scheme si el fibonacci no es impar, no lo guarda. Se podría lograr lo mismo haciendo:


oddFibonacciNumbers := OrderedCollection new.
fibonacciNumbers := 1 to: n do: [ :aNumber | | fibonacci |
fibonacci := aNumber fibonacci.
fibonacci odd ifTrue: [ oddFibonacciNumbers add: fibonacci] ].
^oddFibonacciNumbers

No es tan claro como la versión anterior, por lo que se podría abstraer en algo así:

(1 to: n)
add: [ :aNumber | aNumber fibonacci ]
into: OrderedCollection new while:
[ :aFibonacciNumber | aFibonacciNumber odd ]

De esta manera queda mejor expresada la idea que se quiere implementar.

1 comentario:

Anónimo dijo...

http://markonzo.edu fluctuations http://blog.bakililar.az/biofreeze/ http://blog.bakililar.az/treadmills/ http://www.rottentomatoes.com/vine/showthread.php?p=17358565 midday http://aviary.com/artists/kenou http://www.rottentomatoes.com/vine/showthread.php?p=17358590 spains http://ashley-furniture.eventbrite.com/ http://jguru.com/guru/viewbio.jsp?EID=1534478