son que programming programacion los functional closure functional-programming object oop closures

functional programming - que - "Los cierres son objetos del pobre y viceversa". ¿Qué significa esto?



closures go (6)

Los cierres son objetos del pobre y viceversa.

He visto esta declaración at many places de la web ( incluido SO ) pero no entiendo muy bien lo que significa. ¿Podría alguien explicar qué significa exactamente?

Si es posible, incluya ejemplos en su respuesta.


Los objetos son cierres de pobres.

Considera Java. Java es un lenguaje de programación orientado a objetos sin soporte de nivel de idioma para cierres léxicos reales. Como programador de Java, los programadores utilizan clases internas anónimas que pueden cerrar las variables disponibles en el alcance léxico (siempre que sean final ). En este sentido, los objetos son cierres de pobres.

Los cierres son objetos del pobre hombre.

Considera Haskell. Haskell es un lenguaje funcional sin soporte de nivel de lenguaje para objetos reales. Sin embargo, se pueden modelar utilizando cierres, como se describe en this excelente artículo de Oleg Kiselyov y Ralf Lammel. En este sentido, los cierres son objetos del pobre hombre.

Si proviene de un entorno OO, probablemente encontrará que pensar en términos de objetos más naturales, y por lo tanto puede pensar en ellos como un concepto más fundamental que los cierres. Si proviene de un entorno de FP, podría pensar que pensar en términos de cierres es más natural y, por lo tanto, puede pensar en ellos como un concepto más fundamental que los objetos.

La moraleja de la historia es que los cierres y los objetos son ideas que se expresan en términos de unos a otros, y ninguno es más fundamental que el otro . Eso es todo lo que hay en la declaración bajo consideración.

En filosofía, esto se conoce como realismo dependiente del modelo .


"Los objetos son cierres de un hombre pobre" no es solo una declaración de equivalencia teórica, es un idioma común en Java. Es muy común usar clases anónimas para cerrar una función que captura el estado actual. Así es como se usa:

public void foo() { final String message = "Hey ma, I''m closed over!"; SwingUtilities.invokeLater(new Runnable() { public void run() { System.out.println(message); } }); }

Esto incluso se parece mucho al código equivalente usando un cierre en otro idioma. Por ejemplo, usando bloques Objective-C (ya que Objective-C es razonablemente similar a Java):

void foo() { NSString *message = @"Hey ma, I''m closed over!"; [[NSOperationQueue currentQueue] addOperationWithBlock:^{ printf("%s/n", [message UTF8String]); }]; }

La única diferencia real es que la funcionalidad está new Runnable() en la new Runnable() instancia de clase anónima de new Runnable() en la versión de Java.


EDITADO: El título de la pregunta no incluye "viceversa", así que intentaré no asumir la intención del solicitante.

Los dos campos comunes son idiomas funcionales versus imperativos. Ambas son herramientas que pueden realizar tareas similares de diferentes maneras con diferentes grupos de preocupaciones.

Los cierres son objetos del pobre hombre.

Los objetos son cierres de pobres.

Individualmente, cada enunciado generalmente significa que el autor tiene algún prejuicio, de una forma u otra, por lo general enraizado en su comodidad con un idioma o clase de idioma frente a la incomodidad con otro. Si no es un sesgo, pueden estar limitados con un entorno u otro. Los autores que leo dicen que este tipo de cosas suelen ser fanáticos, puristas o de lenguaje religioso. Evito los tipos de lenguaje religioso si es posible.

Los cierres son objetos del pobre hombre. Los objetos son cierres de pobres.

El autor de eso es un "pragmático" y también bastante inteligente. Significa que el autor aprecia ambos puntos de vista y aprecia que son conceptualmente uno y el mismo. Este es mi tipo de compañero.


El punto es que los cierres y los objetos logran el mismo objetivo: encapsulación de datos y / o funcionalidad en una sola unidad lógica.

Por ejemplo, puedes hacer una clase de Python que represente a un perro como este:

class Dog(object): def __init__(self): self.breed = "Beagle" self.height = 12 self.weight = 15 self.age = 1 def feed(self, amount): self.weight += amount / 5.0 def grow(self): self.weight += 2 self.height += .25 def bark(self): print "Bark!"

Y luego instanciar la clase como un objeto

>>> Shaggy = Dog()

El objeto Shaggy tiene datos y funcionalidad integrados. Cuando llamo a Shaggy.feed(5) , gana una libra. Esa libra se almacena en una variable que se almacena como un atributo del objeto, que más o menos significa que está en el alcance interno de los objetos.

Si estuviera codificando algo de Javascript, haría algo similar:

var Shaggy = function() { var breed = "Beagle"; var height = 12; var weight = 15; var age = 1; return { feed : function(){ weight += amount / 5.0; }, grow : function(){ weight += 2; height += .25; }, bark : function(){ window.alert("Bark!"); }, stats : function(){ window.alert(breed "," height "," weight "," age); } } }();

Aquí, en lugar de crear un alcance dentro de un objeto, he creado un alcance dentro de una función y luego he llamado a esa función. La función devuelve un objeto JavaScript compuesto de algunas funciones. Debido a que esas funciones acceden a los datos que se asignaron en el ámbito local, la memoria no se recupera, lo que le permite seguir utilizándolas a través de la interfaz proporcionada por el cierre.


Tanta azúcar, como cierres ocultan objetos anónimos bajo sus faldas.


Un objeto, en su forma más simple, es solo una colección de estados y funciones que operan en ese estado. Un cierre también es una colección de estado y una función que opera en ese estado.

Digamos que invoco una función que toma una devolución de llamada. En esta devolución de llamada, necesito operar en algún estado conocido antes de la llamada a la función. Puedo crear un objeto que incorpore este estado ("campos") y que contenga una función miembro ("método") que funcione como devolución de llamada. O bien, podría tomar la ruta rápida y fácil ("hombre pobre") y crear un cierre.

Como un objeto:

class CallbackState{ object state; public CallbackState(object state){this.state = state;} public void Callback(){ // do something with state } } void Foo(){ object state = GenerateState(); CallbackState callback = new CallbackState(state); PerformOperation(callback.Callback); }

Esto es pseudo-C #, pero es similar en concepto a otros lenguajes OO. Como puede ver, hay una buena cantidad de repetición en la clase de devolución de llamada para administrar el estado. Esto sería mucho más simple usando un cierre:

void Foo(){ object state = GenerateState(); PerformOperation(()=>{/*do something with state*/}); }

Esta es una lambda (nuevamente, en sintaxis C #, pero el concepto es similar en otros lenguajes que admiten cierres) que nos da todas las capacidades de la clase, sin tener que escribir, usar y mantener una clase separada.

También escuchará el corolario: "los objetos son el cierre de un hombre pobre". Si no puedo o no aprovecharé los cierres, entonces me veo obligado a hacer su trabajo utilizando objetos, como en mi primer ejemplo. Aunque los objetos proporcionan más funcionalidad, los cierres suelen ser una mejor opción donde funcionará un cierre, por las razones ya indicadas.

Por lo tanto, un hombre pobre sin objetos a menudo puede hacer el trabajo con cierres, y un hombre pobre sin cierres puede hacer el trabajo usando objetos. Un hombre rico tiene ambos y usa el correcto para cada trabajo.