El cálculo lambda y el Ceylon de G.King

Al leer la presentación de G. King del futuro lenguaje Ceylon, al que @domix hizo referencia en estos días en este sitio, me sorprendió como a muchos otros en la red, la forma tan "poco agradable" que G. King se refirió al cálculo lambda, tomando en cuenta la importancia de ese concepto en la computación, y también tomando en cuenta el background matemático del autor.
Gavin King en su blog ayer se refirió a ese "missunderstanding" en la blogosfera y escribió una aclaración (sin olvidar su ego) que vale la pena leer. Ahí se los dejo:

Ceylon presentation: a clarification. http://in.relation.to/Bloggers/CeylonPresentationAClarification

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de ezamudio

Liga

La liga realmente es esta. El artículo ya no era el primero en la página principal cuando leí esto.

Para mi, de todo el cuento

Para mi, de todo el cuento que avienta solo resulta importartante:

"The lambda calculus is a formal system for studying the mathematical behavior of functions. "

Y me suena contradictorio el final

"Again, it doesn't really matter to me if you agree or not. ... Now waiting for a flood of apologies from all the folks who've called me "ignorant" over this. I'm looking especially at you, Scala fans ;-) "

Imagen de Jvan

Programación funcional

Saludos comunidad.

De todo esto que se ha hablado sobre nuevos lenguajes para la JVM, la integración de closures, la fuerte tendencia a la programación funcional, yo tengo una duda, según yo la programación funcional es más vieja que la programación orientada a objetos, cuando aprendes POO te dicen que este paradigma vino a resolver muchas carencias de viejos paradigmas como programación estructural y funcional, ¿por qué si se contempla a la POO como el paradigma que vino a resolver tantas carencias ahora se llega la tendencia de la programación funcional?, entiendo que hay muchos problemas que se pueden resolver de mejor manera con programación funcional, estructural, lógica, así como también algunos otros con POO, pero lo que me llama la atención es porque regresar a lo funcional cuando se suponía POO era lo que revolucionaría?

Porque a lo que he leído de los nuevos lenguajes que han salido para la JVM la mayoria estan tendiendo a una programación más funcional, es probable que termine por desplazar a la POO?

Bueno es una simple inquietud que tengo, corrijanme si estoy mal interpretando los conceptos.

Imagen de bferro

Todos los lenguajes de programación se basan en formalismos

Despreciar los formalismos matemáticos en la computación conduce a muchos programadores al fracaso. No distinguen entre tipos y clases, ni entre funciones y métodos, ni en conceptos tan de moda ahora como que las funciones son objetos en un entorno híbrido de programación funcional y programación orientada a objetos.
Uno de los formalismos más importantes para poder entender lo que programamos en un lenguaje funcional es precisamente el cálculo lambda, en particular el cálculo lambda no tipado. G. King lo aclara, y su crítica va más en el sentido de la notación usada en los lenguajes para las expresiones lambdas, comparado con la notación que se usa para estudiar el cálculo lambda en matemática.
Aunque a muchos no les guste, toda persona dedicada a escribir programas debería preocuparse por mejorar su background en varias áreas de la matemática.

Imagen de ezamudio

programación funcional

Visto de manera muy simple, la programación funcional se puso en boga nuevamente porque los problemas de procesamiento de datos en ambientes altamente concurrentes (una computadora con varios CPU's, multicores, procesamiento distribuido de datos, etc) se resuelven de manera más sencilla con programación funcional que con OOP.

Imagen de bferro

Los dominios de los problemas son muy diversos

En este sitio casi siempre se hace referencia a problemas muy centrados a resolver sistemas "empresariales". Ese es el dominio más "poblado" de sistemas de cómputo, pero no es el único.
Muchos problemas muy complejos no caen en ese dominio, por ejemplo, el mundo de los sistemas inteligentes para resolver muchas cosas también muy importantes.

En esos otros dominios, la programación funcional es muy usada, así como la programación lógica, etc. Hay mucha gente en el mundo que gana muy buen dinero haciendo uso de esos paradigmas.

Algunos creadores de lenguajes con un background fuerte en programación funcional, se dan cuenta que sus productos pueden tener éxito si se combina la programación funcional con la programación orientada a objetos, pues esta última es la que prevalece en la mayoría de las aplicaciones actuales. Es una de las razones por la cual el lenguaje Scala no se sale de los conceptos fundamentales de la programación orientada a objetos, al introducir en el lenguaje programación funcional.

El artículo "Why Functional Programming Matters" http://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf
que ya tiene más de 20 años, es casi una lectura obligada.

Martin Odersky, al presentar Scala, hace mucho énfasis en los problemas actuales para diseñar sistemas basados en componentes. Una de las promesas de la orientación a objetos es precisamente esa; la de brindar un paradigma más adecuado que la programación procedural para crear componentes reusables de software.

Copio a continuación un par de párrafos de uno de sus artículos: (espero que no me apabullen diciendo que es extenso)

Scala fuses object-oriented and functional programming in a statically typed programming language. It is aimed at the
construction of components and component systems.
................................
True component systems have been an elusive goal of the software industry. Ideally, software should be assembled from libraries of pre-written components, just as hardware is assembled from pre-fabricated chips. In reality, large parts of software applications are written from scratch, so that software production is still more a craft than an industry.

Components in this sense are simply software parts which are used in some way by larger parts or whole applications.
Components can take many forms; they can be modules, classes, libraries, frameworks, processes, or web services.
Their size might range from a couple of lines to hundreds of thousands of lines. They might be linked with other components
by a variety of mechanisms, such as aggregation, parameterization,inheritance, remote invocation, or message passing.
We argue that, at least to some extent, the lack of progress in component software is due to shortcomings in the programming languages used to dene and integrate components. Most existing languages oer only limited support for component abstraction and composition. This holds in particular for statically typed languages such as Java and C# in which much of today's component software is written.
There are two hypotheses that we would like to validate with the Scala experiment. First, we postulate that a programming language for component software needs to be scalable in the sense that the same concepts can describe small as well as large parts. Therefore, we concentrate on mechanisms for abstraction, composition, and decomposition rather than adding a large set of primitives which might be useful for components at some level of scale, but not at other levels. Second, we postulate that scalable support for components can be provided by a programming language which unies and generalizes object-oriented and functional programming. For statically typed languages, of which Scala is an instance, these two paradigms were up to now largely separate.

La programación funcional

La programación funcional tiene entre sus características principales la inmutabilidad y el uso de funciones como principal elemento de construcción.

Con la llegada de mejor hardware y la necesidad de más capacidad de procesamiento, estas características resultaron particularmente atractivas para el desarrollo de sistemas. Por ejemplo ( y no estoy diciendo que estos usen exclusivamente programación funcional, pero si lo usan en partes ) Twitter, Google y otros necesitan trabajar una petición entre miles procesadores en milisegundos. Para hacerlo el paradigma funcional sirve muy bien por las dos características anteriores.

Cuando Google publicó su papel de Map Reduce este estilo de programación volvió a tomar auge. Cuando Twitter hizó público que estaban migrando parte de su backend de Ruby a Scala muchísima gente ( como siempre pasa ) pensó: si a ellos les funciona a mí también.

Es interesante recalcar que cualquier paradigma de programación se puede intentar con cualquier lenguaje de programación, lo que sucede es que resultará mucho más difícil por ejemplo hacer "objetos" en C o Basic aunque no es imposible. De la misma manera no es imposible hacer programación funcional en Java, pero es muchísimo más fácil hacerla en Haskell o Lisp ( o Clojure for that matter ) y pareciera masoquismo intentarlo.

Inmutabilidad y los efectos secundarios.

En matemáticas ( y en la programación funcional ) llamar dos veces a una misma función debe de dar SIEMPRE, SIEMPRE, SIEMPRE el mismo resultado, aunque se llame un trillón de veces. Se dice que las funciones no tienen efectos secundarios. Por ejemplo:

Si de define:

f(x) = x + 1

Cuando se le pasa x = 1 siempre debe de dar 2 S - I - E - M - P - R - E ( lo repito muchas veces porque es quizá la característica más importante en la PF )

imprimir  f(1) // imprime 2

En la programación orientada a objetos llamar 2 veces al mismo método puede NO dar el mismo resultado, porque puede depender del estado del objeto. Por ejemplo el clásico contador que cada vez que se llama incrementa una variable de instancia c

// En dizque Ruby
class Contador
   def f(x)
       @c = @c + x
       return @c
   end
end

Si se llama 10 veces, regresa resultados diferentes cada vez para el mismo parámetro:

contador = Contador.new()
print contador.f( 1 ) // imprime 1
print contador.f( 1 ) // imprime 2

En la programación orientada a objetos se modela para que el objeto sea el responsable de mantener el estado del dato, llamar a los métodos puede tener efectos secundarios ( el efecto secundario es que la variable c se incremente en uno ).

Cuando un objeto o mejor dicho un dato se pasa entre dos hilos ( o entre dos procesadores ) se necesita un procesamiento extra para asegurar que el estado no se corrompa. En Java, esto se hace con candados, sincronización y varios artefactos más que no vienen a cuento y de los que Enrique ha posteado varias entradas aquí en Java México.

Cuando los datos son inmutables, esto ya no es necesario, porque se sabe que ... bueno los datos no van a cambiar y no hace falta sincronizarlo ahorrándose así valiosos milisegundos de procesamiento. Luego entonces ( por ejemplo ), una consulta de Google se puede pasar a 1 o un millón de procesadores al mismo tiempo.

Funciones

Como las funciones, no tienen efectos secundarios y como las funciones son los elementos principales en la PF se puede hacer la iteración de una lista con una función en vez de un ciclo for.

Este iteracione se podría hacer con varios procesadores el mismo tiempo. Usando OO o procedural se puede usar un ciclo for:

// OO o Procedural

lista = .... //obtenerla de algun lado
for each elemento in lista
   hazAlgoCon( elemento )
end

En un lenguaje OO o procedural el ciclo for debe de ser ejecutado por un solo procesador mientras que:

// en programacion funcional
list = // obtener la lista de algun lado
// doF es una función
doF =  function (elemento)  {
   hazAlgoCon( elemento )
}
list.each( doF )

La implementación de "each" puede hacer uso de varios procesadores al mismo tiempo y simplemente recibe otra función que le dice que es lo que hay que hacer.

Cuando la lista tiene 1,000 elementos quizá no haya mucha diferencia pero cuando la lista tiene 1,000 millones el impacto es importante.

Por ejemplo cuando un tweet de Lady Gaga tiene que ser notificado a todos los que le siguen.

Conclusión

Estas son a grandes rasgos dos caracterísicas que han traído de nuevo al mapa a la programación funcional. Las razones son puramente prácticas, la necesidad de modelos de procesamiento que soporte millones procesadores.

Estos paradigmas no son nuevos, pero no habían tomado tanto auge principalmente porque el hace no muchos años ( 30 años por ejemplo ) un programa hecho en C corría muchisimo más rápido que uno escrito en Lisp por el hardware de entonces.

Varias clases de Java son inmutables precisamente tomando guía este principio de la PF. Javascript fue totalmente modelado basándose en Scheme ( un dialecto de Lisp ) pero forzado a que se pareciera a Java. Etc. La mejor forma de hacer progamación concurrente es usando datos imutables. etc.

La programación funcional NO va a reemplazar a la Orientada a Objetos, de la misma manera que la programación orientada a objetos no borró del mapa a la funcional inicialmente. Simplemente se van a seguir complementando recriprocamente ( de la misma forma que la programación orientada a objetos absorbió mucho del modelo procedural ) Hay quién dice que se está creando el paradigma ObjectFunctional FTW :) Y Scala sería un excelente ejemplo de este ObjectFunctional ( sobre todo a los que se ofenden cuando se le llama híbrido )

Smalltalk por ejemplo, es un lenguaje que desde el principio usó bloques de código como elementos principales y que podrían ser pensados como funciones o closures, pero la diferencia entre Smalltalk y los lenguajes funcionales es que su descripción ( la semántica de su sintaxis ) dijo: "Estos son objetos. Los objetos se comunican con mensajes. Se pueden pasar bloques de código que son también objetos etc." Es decir, su énfasis fué en los objetos como principales artefactos de construcción.

Monadas

En la programación funcional no hay estado mutante, ( por ejemplo agregar un elemento a una lista, regresa una lista diferente con un elemento más) pero SI pueden "simularlo" ( es como una forma en PF de admitir que si hace falta estado mutante sin tener que morderse la lengua ) a través de "Monads" que a veces parece ser más bien un término hecho para asustar a los programadores no funcionales. Las monadas en mis términos simples, sencillos y muy probablemente incorrectos es una forma de modificar el estado de un dato de forma legal. Por ejemplo se usa para imprimir en la consola, que estrictamente hablando sería un dato no mutable y por lo tanto no se podría escribir en él, pero con el IO monad ya se puede. Para entender más de Monads está este excelente blog, que fue el único que logré digerir de varios que se me encontré: Los Monads no son metáforas por Daniel Speiwak.

Espero que esta información les sea útil.

Yo he visto en este tiempo

Yo he visto en este tiempo que mas que por la capacidad del manejo de datos, un lenguaje se ha hecho mas popular por sintetizar codigo... creo que muchos nos hemos vuelto flojos para escribir codigo ya muy conocido como por ejemplo en vaidaciones, en ciertos calculos ya muy triviales entre otras cosas...

Por que digo que NO veo que esten mas enfocados al rendimiento e el procesamiento de datos y SI en la reduccion de lineas aplicables para hacer algo pues sencillo que todo va sobre JVM y lo que he visto es que solo se preocupan por la sintaxis del lenguaje, en el como se ve, el como se deberia de ver y el como no me gusta que se vea pero (personalmente) creo que en rendimiento no les ha venido preocupando si x lenguaje es mas lento qe Java o si tiene mejor acceso al procesamiento nato de la informacion... yo sinceramente veo que muchos mas estan preocupados por la estetica del lenguaje... bueno biene tambien la funcionalidad y tambien miran que se pueda hacer mas facil aunque sacrifique la rapidez que tiene java

Yo digo que es solo para sintetizar codigo porque detras de todas las cosas que hagamos con algun alternativo para JVM esta presizamente eso JVM y mientras no cambien (para optimizar en cada lenguaje alternativo que surja) la JVM no habra diferencia a mejora de rendimiento (pienso yo)...

Preparado para que me vengan comentarios de gran contenido ofensivo me atrevo a decirles que pense en algun momento: "los lenguajes aternativos son para flojos que no quieren escribir mas codigo" y claro, en cierto aspecto he estado equivocado en pensar eso porque como ya dije alguna vez: "java no tiene una sintaxis que se pueda traducir directamente a lo humanamente usado" es por eso que si usamos Java hay que pensar como Java y asi mismo con cada lenguaje que se esté usando... yo veo que Por ejemplo Scala y Groovy y lo poco que he leido de Ceylon estan perdiendo esa onda de POO y ues claro porqe estan diseñados para otro paradigma mas "Funcional"

Yo hasta el momento no he tenido broncas con Java tal como es pero si tengo que reconocer que en otros lenguajes alternativos es mas COMODO programar

@java.daba.doo Si piensas que

@java.daba.doo

Si piensas que la PF es para escribir código más fácilmente es porque no has visto un ejemplo escrito en Lisp je je je

Tampoco es precisamente para enfocarse al rendimiento, pero como escribí acá arriba ciertos paradigmas hace más fácil la programación concurrente ( Immutabilidad y First class Functions )

Imagen de ezamudio

comodidad

No hay nada de malo en preferir un lenguaje sobre otro por pura comodidad o brevedad (escribir menos código), especialmente si por ejemplo ambos usan la misma plataforma y la misma infraestructura. Tal es el caso de Groovy como mencionas. Puedes preferir Groovy sobre Java simplemente por la brevedad: ya no usas punto y coma, puedes hacer objeto.propiedad=valor en vez de objeto.setPropiedad(valor), ya no tienes que escribir getters y setters por default (ni la palabra private), y varias otras monerías de Groovy que hacen que sea más breve que Java.

Pero eso es sólo el principio. Si te quedas ahí, estás desperdiciando mucho del poder del lenguaje que elegiste. Groovy por ejemplo tiene closures, que podrías no usar si no quieres, pero es gran parte de lo que puede hacer tu código más breve y en ocasiones más entendible; cuando haces una aplicación o un sistema con Groovy, en vez de un simple script, el diseño del mismo va a cambiar si consideras aprovechar las características del lenguaje como closures, transformaciones AST, metaprogramación, crear tus propios DSL's, etc.

Y pues hay una gran diferencia entre los que solamente usan un lenguaje u otro por comodidad, los que usan un lenguaje u otro porque es el más apropiado para resolver el problema que tienen enfrente, y los que diseñan un lenguaje pensando en cierto dominio de problemas. Scala por ejemplo lo veo muy enfocado a ambientes altamente concurrente, me recordó mucho la filosofía de Erlang, pero usando la JVM. Sería interesante sin embargo, ver la diferencia de desempeño entre Erlang y Scala, ya que Erlang algo que tiene muy a su favor es que no hay que usar miles de hilos sino que maneja procesos internos, evitando context switching lo cual incrementa la velocidad de manera notable.

Así que si te refieres a que hay muchos programadores Java que prefieren cambiar a un lenguaje alterno por comodidad, estoy de acuerdo, y no lo veo como algo malo, siempre y cuando una vez que se sientan cómodos en el nuevo lenguaje, aprovechen las características que ofrece. Pero si te refieres a que estos lenguajes están saliendo por esa misma razón, estás muy equivocado. Los autores de Groovy, Scala, Clojure, etc no tenían en mente hacer un lenguaje más breve que Java, no era la meta, aunque sea un bullet point en la presentación que hagan de su lenguaje. Hicieron un lenguaje nuevo con muchas características que Java no ofrece, porque es lo que sentían que le falta a Java, porque necesitaban de (o simplemente querían tener) un lenguaje funcional para alta concurrencia que aprovechara todo lo que ya tiene la JVM, o porque querían un lenguaje híbrido OOP-funcional con tipado dinámico, etc.

Imagen de greeneyed

Lo que viene a explicar Gavin

Lo que viene a explicar Gavin King es que lo quería decir es que en Java se usa una notación más común para llamadas a funciones etc. [estilo f(x,y)] que la que se usa en teória de computacion de cálculo lambda (sin paréntesis etc.) y que él cree que eso le permitió convertirse en un lenguaje popular.
Ni menosprecia la teoría de computación, ni dice que una forma sea mejor que otra ni nada parecido. Simplemente quería decir que cree que usar una notación más común permitió a más gente aprenderlo más rápido y convertirse en un lenguaje popular.

Y admite que sacadas fuera de contexto, esas dos frases pueden interpretarse de múltiples formas.

Por supuesto, la gente escojerá la que mejor le convenga a sus intereses: para meterse con él o para entenderlo y mucha gente, especialmente del campo teórico matemático lo cogió por donde quiso y le puso a caldo. A esos les sumamos los típicos trolls de internet que se suman a cualquier cosa que parezca un linchamiento y tienes el follón servido.

A mi personalmente, lo que me sorprende es que no se esperara este tipo de reacción, visto lo visto como está Internet y las comunidades de cada lenguaje. Con su trayectoria en Internet ya debería estar más curtido :). Es curioso también que la comunidad que menos le he visto atacarle es la del lenguaje que se supone ha de sustituir (Java).

Por cierto Bferro o

Por cierto Bferro o alguien más, si pudieran hacer un post sobre el Cálculo Lambda estaría super.

He podido deducir que es a partir de otras coas pero la verdad es que siempre entro en modalidad blablah. :P

Quizá una descripción más sencilla me ayudaría ( como con la varianza ) a verlo con otros ojos.

Imagen de bferro

La programación concurrente es otro boleto

Los problemas de la concurrencia no han sido resueltos con la programación funcional, aunque algunas cosas que los modelos de programación concurrente han propuesto, se pueden implementar mejor con la programación funcional que con la programación imperativa, pero no de manera relevante.
Los modelos de concurrencia de procesos independientes que se comunican por paso de mensajes pueden ser usados tanto en un ambiente imperativo como en uno funcional. Es el caso del modelo de Actor, que es usado tanto por lenguajes imperativos como por lenguajes funcionales, con una distinción grande en el diseño e implementación de los procesos y actores.

El reto actual de la programación es precisamente el de la concurrencia. Está sucediendo lo que siempre ha sucedido y es que el hardware disponible no es aprovechado por el software por su incapacidad para la concurrencia.
No existe aun un consenso de qué modelo de concurrencia debe ser el más adecuado. Quedan aun muchas cosas por resolver tanto para la concurrencia con bloqueo como para la concurrencia sin bloqueo.