Programación funcional (Scala, Clojure, etc.)

elkaoD

Visto que en el hilo de MV Coders on fire despertaron cierto interes Haskell/Lisp y derivados (y que acabé con una conversación paralela con Eisenfaust) me decido a abrir este hilo propio para el tema.

Supongo que no tendrá mucha actividad pero pretendo que quede como "cajón de sastre" de todo lo funcional a pesar de lo muy diverso de sus lenguajes (es como hacer un hilo de POO, pero por separado tendría aún menos actividad...)

Aquí en #1 pretendo recopilar pequeñas descripciones/enlaces/snippets/loquesea de cada lenguaje. Me da pereza hacer muchos así que iré poniendo poco a poco (y obviamente acepto colaboraciones.)

La idea que tengo con este thread es en primer lugar dejar de derailear threads (no es la primer vez que acabo hablando de funcional con Eisenfaust en otros hilos) y sobre todo, a ver si se anima alguien a probar la programación funcional (evangelización ftw!) Además es un buen punto de recogida de información/enlaces tanto para mí (que suelo perder todos los enlaces) como para compartir con el resto.

Programación funcional: ¿qué es?

La programación funcional (Wikipedia inglés, español) es un paradigma de programación que trata la computación como la evaluación de funciones (funciones en el sentido matemático, p.ej. f(x)), evitando estados y datos mutables. Establece su énfasis en la aplicación de funciones para la consecución de un objetivo, frente al paradigma imperativo, que enfatiza los cambios del estado interno de la computación (asignación a variables.)

Históricamente se puede considerar a la programación funcional como una evolución del cálculo lambda (de ahí que aparezcan tantas lambdas en los logos de los lenguajes funcionales, y ciertas funciones en algunos se llamen lambda.) El cálculo lambda es un sistema formal desarrollado en los años 30 por Church y Kleene para investigar la definición y aplicación de funciones y la recursividad. No cumplió realmente su objetivo como sistema de formalización, pero sí encontró un hueco en la teoría de la computación.

La mayoría de lenguajes no son puramente funcionales, si no que incorporan características del paradigma, del mismo modo que C++ no es puramente orientado a objetos y pemite programación imperativa.

- Ventajas

  • Flujo de ejecución previsible

  • Favorece pequeños bloques de ejecución

  • Pruebas unitarias más cortas y extensivas

  • Reusabilidad

  • Mayor facilidad para la ejecución concurrente

Diferencias con la programación imperativa

- Enlaces

Lisp y dialectos

...

- Enlaces

Scala


Scala
(Wikipedia inglés, español)

Scala es un lenguaje de programación multi-paradigma, ya que incorpora características de programación orientada a objetos, funcional, concurrente... Soporta como plataformas Java (corre sobre la JVM) y CLR (Common Language Runtime de la plataforma .NET, aunque el soporte es menor.) Es completamente interoperable con sus plataformas: puedes llamar a código/clases/librerías Java (o .NET en CLR) desde Scala y viceversa.

El objetivo de Scala es mantener una sintaxis limpia y concisa que permita escribir código breve. Además cabe destacar que, a pesar de mantener el tipado estático (exactamente igual que Java) el compilador infiere los tipos donde es posible, por lo que la mayoría del código tiene el mismo aspecto que tendría en un lenguaje con tipado dinámico.

Otra gran característica es su extensibilidad. Es fácil crear nuevos constructos para el lenguaje que adquieren la apariencia de pertener al lenguaje en sí. Además, hacer esto no requiere de creas costosas macros si no que el flujo de extensión es prácticamente el mismo que escribir un programa. Gracias a esta extensibilidad se pueden implementar pequeños DSLs (Domain Specific Languages) dentro de Scala.

Ejemplos de código

- Enlaces

- Libros, documentación...

Clojure

Clojure (pronunciado "closur") es un lenguaje de programación funcional (híbrido) orientado a la programación multi-hilo. Es un dialecto de Lisp integrado en distintas plataformas: JVM (Java), CLR (.NET) y JavaScript, permitiendo interoperabilidad con estas. La motivación para desarrollar (otro) dialecto de Lisp viene de la necesidad de un Lisp moderno (frente a los desactualizados estándares de Common Lisp o Scheme) en simbiosis con plataformas ya establecidas y diseñado de base para la concurrencia.

Como el resto de Lisps (ver sección Lisp y dialectos más arriba) es homoicónico, es decir, no distingue entre datos y código. Su sintaxis se basa en S-expresiones (estructuras de datos basadas en listas) que son parseadas y posteriormente compiladas. Soporta sintaxis literal para listas (), vectores [], mapas {} y conjuntos #{}. Es un Lisp-1 (soporta usar funciones en variables como una función normal) pero no es compatible en código con otros dialectos. Como característica diferente al resto de Lisps implementa multimétodos, permitiendo polimorfismo estilo OOP.

Clojure favorece el desarrollo incremental en su intérpreto o REPL (read-eval-print loop) aunque también permite la ejecución de scripts y compilación a sus respectivas plataformas.

Ejemplos de código

- Enlaces

- Libros, documentación...

8
HeXaN

Bastante interesante. Si lo usa Twitter, tiene que ser bueno xD Algún día me pondré a darle caña a ver qué sale.

eisenfaust

También cabe destacar que últimamente y al menos en el sector finanzas y banca de inversión (donde generalmente se ha invertido muchísimo en lenguajes funcionales tipo Hindley-Milner) la mayoría de compañías están migrando de Haskell y Ocaml al reciente F#.

Yo creo que actualmente Scala y F# son los lenguajes que ofrecen más ROI en este sentido. La cuestión ya no es qué lenguaje utilizar, sino elegir entre CLR vs JVM.

Personalmente me quedo con Clojure y F#. Scala es bastante feo xD

--

Estaría bien que se diesen permisos de edición en #1 para el resto de usuarios que quieran contribuir.

En cuanto a la "wiki" de lenguajes. ¿Cuál es el criterio para incluirlos? Porque Common Lisp o Scala no es que sean funcionales, son multiparadigma, y en este sentido son tan funcionales como lo pueden ser, por ejemplo, Factor, Oz o Perl.

2 respuestas
elkaoD

#3 el criterio que he seguido es no sólo que permitan funcional si no que sea "core" en el lenguaje, es decir, que su filosofía y biblioteca estándar lo fomenten. Creo que es lo más lógico porque si no esto se queda vacío (¿qué lenguajes hay puramente funcionales en realidad?) o muy lleno.

P.ej. Python permite funcional pero ¿qué tiene? lambda, map y poco más... no lo clasificaría en #1 y, de hecho, normalmente sale "raro" escribir funcional en Python. Sin embargo creo que sí tendría cabida en el hilo comentar CÓMO usar Python para aplicar funcional.

¿Qué os parece?


Por cierto, aprovecho para insistir con 4clojure. Hay un montón de problemas de diferentes dificultades. Son estilo rellenar-el-hueco: te muestran un enunciado y ciertas pruebas unitarias que debe pasar el código una vez contestes. Todo vía web.

Además hay una liga de code golf (hay que apuntarse para participar) y al resolver te muestra tu puntuación en un bonito gráfico con las puntuaciones globales.

Y lo mejor de todo es que una vez contestado puedes ver las soluciones del resto de usuarios (que tengas en follow) y aprender de ellos. A mí me está viniendo genial para aprender. Las pruebas están muy bien planteadas para que progreses poco a poco, y hay verdaderos máquinas del code-golf de los que aprender.

Aquí mi perfil por si alguien se apunta que me haga follow (mp y devuelvo el follow!)

storm2211

yo estoy ahora metido con erlang y me parece una maravilla el soporte que ofrece concurrencia y programacion de redes, algo que solo habia tocado en Java y se ve una diferencia terrible.

1 respuesta
Gusete

#3 desde mi vision limitada de la industria de finanzas (hedge funds, algo, trading, hft, etc...) es casi todo C++ (con template metaprogramming a saco) y algo he visto de F# pero casi nada. Tambien algo de C# para el frontend pero poco mas.

1 respuesta
eisenfaust

#6 Sí, es todo C++ por razones obvias.

También se suelen ver en producción Java y C# y en desarrollo R, Python y especialmente VBA.

Lo que quiero decir con mi post es que dentro de esta industria, que es históricamente la que más ha expresado interés en este tipo de lenguajes y por ende un lugar donde terminan muchos adeptos a la programación funcional, la tendencia ahora mismo es utilizar F#, en lugar del difunto Ocaml y del hypeado Haskell.

Lo que no quise insinuar ni mucho menos es que sean utilizados ampliamente en este sector ni en ningún otro. Precisamente Scala, siendo (creo) el lenguaje de este tipo más utilizado apenas llega al 0.60% de share en UK.

1 respuesta
elkaoD

#5 cómo funciona la concurrencia en Erlang? Es otro de los lenguajes a los que le tengo ganas, a ver si saco tiempo y le doy duro.

#7 a qué te refieres exactamente con Haskell hypeado?

1 respuesta
eisenfaust

#8 Me refiero a que desde hace unos tres años o así se está viendo un hype desmedido que no corresponde al uso real del lenguaje en la industria. r/haskell es de los subreddits más activos en cuanto a programación funcional, lo mismo con #haskell en FreeNode, hay un zillión de blogs comentando cómo empezar a programar en él, se publican libros, se crea el CUFP… Y a la hora de la verdad, nada. Estamos a 2012, su uso en la industria es tan bajo como el de Ocaml y las únicas aplicaciones medio terminadas en Haskell son darcs y xmonad.

0buS

Dios que bien me viene este post. Tengo justo examen pronto de Lenguajes y paradigmas de la programación xD

1 respuesta
eisenfaust

#10 http://www.info.ucl.ac.be/pvr/VanRoyChapter.pdf

Y ve abriendo boca para http://www.amazon.com/Concepts-Techniques-Models-Computer-Programming/dp/0262220695

xD

1 respuesta
elkaoD

#11 busco una web (¿diapositivas creo?) que echaba por tierra medio GoF con programación funcional.

Me suena que lo enlazaste pero no encuentro tu post y ya no tengo acceso al link que colgaron en mi universidad.

EDIT: Menos mal que se me vino a la cabeza Peter Norvig. Lo encontré:

Design Patterns in Dynamic Languages

eisenfaust

Gráfico de influencia en lenguajes funcionales

Si Qi/Shen no se ha visto influenciado por Prolog apaga y vámonos...

Source: https://gist.github.com/2576547

1
BLZKZ

para mi falta uno con "bastante" uso en entorno linux que es Haskell xD y es el unico que he probado

1 respuesta
elkaoD

#14 dices en #1 o en el gráfico?

En el gráfico está. En #1 no, pero puedes arreglarlo :P

1 respuesta
BLZKZ

#15 me referia a #1 . Después del partido si me da tiempo pongo algo chuli de haskell

1
eisenfaust

Functional Languages 101: What’s All the Fuss About?

http://www.infoq.com/presentations/Functional-Languages-101

1 1 respuesta
Josekron

En su día aprendí Haskell en la universidad y por ejemplo trabajar con estructuras de datos es más eficiente y rápido que con lenguajes imperativos. Eso sí, hay que tener la mente un poco más abierta que con los lenguajes imperativos, personalmente me costó horrores entender como implementar grafos y arboles pese a que en Java o C los implemento en un plis. Una vez aprobado no lo volví a tocar xD

1 respuesta
elkaoD

#17 mola el análisis. Es una gran explicación para el que viene de nuevas. El título de "what's all the fuzz about" le viene que ni pintado :)

#18 no sé muy bien como irá Haskell pero un grafo no son más que listas de adyacencia y los árboles una jerarquía de listas (o también lo puedes implementar como un grafo particularizado.) Vamos, igual que en C. ¿Nope?

En mi opinión lo más difícil de cazar no es cómo implementar árboles si no cómo trabajar con ellos (quizá eso es a lo que te refieras.) Aunque a mí no me costó excesivamente (he trabajado más con árboles recursivamente que imperativamente) entiendo que puede ser lo más complicado.

Para mí, lo mejor para aprender funcional es olvidarte de todo lo que sabes, coger un buen libro introductorio y pasearse por los ejemplos como un cabrón.


Por cierto, en los comentarios de la conferencia en #17 hay un post bastante interesante y que imprime una de las ideas a las que más vueltas le llevo dando sobre la PF. Transcribo literalmente:

Post chachipiruli

Hay algo que le discutiría: la reusabilidad no creo que sea un problema. IMHO la PF facilita aún más la reusabilidad al NO encapsular abstracciones si no que las propias abstracciones (las funciones) encapsulan todo lo necesario para trabajar. Encapsulas sólo trabajo (acciones) sin necesidad de añadir un intermediario "innecesario": el estado (parece un discurso anarquista xD) Luego puedes encapsular sobre namespaces (en los lenguajes que lo soportan) y demás pero sin necesidad de encapsular estado (insisto porque es la clave) ni sobre tipos, es decir, abstracción sobre abstracción, que es precisamente lo que hace menos reusables los lenguajes no-funcionales (y lo que elimina su "concurribilidad".)

Sin embargo creo que da en el clavo con lo de la interfaz como "blueprint" del programa (y no voy a explicar por qué, ya lo dice él.)

Es por eso que me gusta tanto Scala: no fuerza la programación funcional. Es mucho más fácil trabajar funcionalmente (y lo fomenta) PERO al tener como paradigma OO permite esos blueprints de forma natural. Además permite trabajar imperativamente en caso de ser necesario (aunque te disuade de hacerlo.)

OJO: en PF también se podría hablar de blueprints y API. Como dije antes sólo con que haya namespaces (Clojure por ejemplo tiene) se podría hablar de abstracciones pero normalmente los namespaces son UN HORROR en todos los lenguajes mientras que la encapsulación en tipos es mucho más natural (realizas operaciones SOBRE tipos y no CON tipos.) Las operaciones no van unidas a los tipos lo que favorece la reusabilidad (pero disminuye el "blueprinting" al estar menos abstraído.)

No puedo hablar mucho de funcionales-tipados porque de momento sólo he trabajado con Scala (que no es puramente funcional) y LISP-like (que carece de tipos, excepto Clojure que es medio raruno al ir sobre JVM.) Tocará toquetear tipados.

La opinión que me he formado de momento es que van contrapuestas: reusabilidad implica de-abstracción mientras que el "blueprinting" requiere de abstracción (see what I did there?) De nuevo, por eso me gusta Scala: te permite elegir tu término medio y además de una forma muy inteligente (y transparente al programador) ayuda a que incluyas nuevos tipos para las operaciones, fomentando así la reusabilidad incluso con la re-abstracción de la que hablaba (a costa de menos purismo, con todo lo que ello conlleva.)

¿Alguna opinión/idea/insight?

3 respuestas
BLZKZ

#19 el tema chachi piruli de haskell son las monads xD

Es que he intentado hacer algo como lo de #1 de haskell pero :/

1 respuesta
elkaoD

#20 lástima porque como digo yo sólo he trabajado con Lisp-like y me gustaría un acercamiento a Haskell. De monads sólo conozco un pequeño acercamiento que hice con una librería de Clojure pero como no están integradas en el lenguaje queda todo un poco chusquero.

No sé si #1 se podrá poner en plan community-wiki para que edite la gente (hablaré con Pirado) pero estaría bien.

De todas formas si te acabas animando (os acabáis, mejor dicho... ¿me oís cabrones? :P) en algún momento del espaciotiempo simplemente postéalo y lo incluyo en #1. Como si es una micro-introducción, un par de enlaces... lo que sea*.

  • véase mi parte sobre Lisp que se quedará a medias para siempre a este paso xD
Josekron

#19 Si, me refería más bien a trabajar con ellos ya que no siempre era el típico árbol BST o AVL, en los exámenes los profesores nos proponían arboles, grafos u otra estructura con algo en particular y no me resultaba nada fácil implementarlo en Haskell.

eisenfaust

+1 a la wiki

Hora de compartir algunos links...

Para aprender Haskell el mejor recurso es éste http://learnyouahaskell.com/

Uno de los mejores libros introductorios para un lenguaje que se hayan escrito. Lo más gracioso es que creo que su autor aún no ha terminado su carrera xD Todo un crack.

Luego está bien seguir con éste http://book.realworldhaskell.org/read/

El autor es de los pocos que ha utilizado Haskell en la industria con relativo éxito. Hace poco hizo una charla muy interesante sobre el uso del mismo en su startup. A ver si la encuentro.

Y personalmente, mi enlace favorito: http://yannesposito.com/Scratch/en/blog/Haskell-the-Hard-Way/

Conciso y directo al grano.

En cuanto a lo que comentas en #19, related: http://www.haskell.org/haskellwiki/OOP_vs_type_classes

B

Yo estoy con Erlang (con mucha calma, reconozco que me cuesta). Me recomendáis ejercicios? Yo estoy siguiendo este libro.

Pero me gustaría acompañarlo de ejercicios, porque llevo ya unos cuantos capítulos y empiezan a costarme algunas cosas.

Un saludo :)

PD: Me respondo yo mismo: http://www.erlang.org/course/exercises.html

A ver cuando tengo un poco de tiempo :)

PD2: Una pregunta para los que sepan de Erlang. Cuál es la mejor forma de tener un código, así:

spoiler

O con las funciones internas detrás de las que exportas? En plan:

spoiler

Yo lo veo más claro de la primera forma (o no :s).

EDIT: Viéndolo así apuesto por la segunda xDD

SicKneSs

En la carrera di un poco de Scheme... era bastante intuitivo.

eisenfaust

A ver si este finde saco un par de horas y preparo la sección de Lisp. Con su historia, diferencias entre principales dialectos e implantaciones... desde LISP I a Arc y Shen.

1 respuesta
elkaoD

#26 lo que me hace recordar...

eisen, tienes poderes de edición en #1 (no sé si te avisaron)

Todo el que quiera aportar, ¡avisad y tendréis poderes mágicos!


Cuanto más trabajo con Clojure más echo de menos pattern matching. Cuanto más trabajo con Scala, más echo de más los objetos...

1 respuesta
bloodhound

Hice un trabajo en Lisp para la asignatura de inteligencia artificial y es la peor mierda que me he echado a la cara. A ver es bonito y muy potente, pero acabas harto de tanto paréntesis.

Prolog hubiera estado mucho mejor.

1 respuesta
eisenfaust

He estado este rato mirándome este vídeo.

No es muy reciente, pero sigue siendo aplicable a cómo se programa CL hoy en día, a excepción de que se usaría Quicklisp en lugar de ASDF.

#27 Por lo visto han movido la lib match del contrib al core.

https://github.com/clojure/core.match

Como curiosidad también puedes echarle a un ojo a Shen. Viene con pattern matching y tiene tipación opcional. De hecho su tipación es bastante superior a la de Scala y Haskell.

Pero es eso, simple curiosidad, porque el lenguaje dudo que vaya a ninguna parte xD

Eso sí, creo que es junto a Racket lo más avanzado que existe actualmente en cuanto a lenguajes de programción.

http://www.shenlanguage.org/

1 respuesta
elkaoD

#28 con Lisp e IA ando yo ahora mismo xD

Lo de los paréntesis es fundamentalmente un problema pedagógico: nadie te ha enseñado como organizarlos para que no den asco. Yo los paréntesis NI LOS VEO, para mí no significan casi nada (en cuanto a organización del código se refiere.)

La historia es simple, paréntesis abierto = dos espacios de indentación. Yo además indento los ifs y demás cosas "relacionadas" a la misma altura. Parece una gilipollez pero ayuda MUCHO a clarificar el código.

Luego de los paréntesis se encarga el IDE que, por muy malo que sea, debe tener resaltado de paréntesis (el actual y el que corresponde.) Como te digo yo ya no miro los paréntesis, son más para el reader que para mí.

#29 ¿Tengo que estudiar y me plantas ese video? :(

Justo por Shen lo decía, lo estaba viendo y me ha recordado a las múltiples veces que he echado de menos pattern matching en Clj. Lo más parecido que hay en el lenguaje es el sobrecargado por aridad. La librería match la conozco pero nada como integración en el lenguaje.

Quiero decir... vale, muy bonito, pero hay que reinventar la rueda para hacer pattern matching sobrecargando funciones (o yo soy muy inhábil.) No sé cómo funcionará en otros lenguajes pero a mí me parece de lo más natural que la lista de argumentos sea un patrón más.

No tenía ni idea de que la habían subido a core, no está ni en clojuredocs. ¿Esto cuanto lleva así?

1 respuesta