[PyVigo] [Py-MAD] [Py-ES] Don’t Use Recursion In Python Any More,Python Closure — A Pythonic technique you must know

Chema Cortés pych3m4 en gmail.com
Mar Ene 12 11:25:23 CET 2021


Hola, José Luis:

Guido suele decir que las características funcionales de python se usan muy
poco porque no se llegan a entender. Ese fue el motivo, al menos, para que
la función reduce dejara  de estar en builtins y acabara en el módulo
functools.

El cálculo lambda de Church sí que está relacionado con la transparencia
referencial, pero no dice nada de clausuras. La idea es que mediante
"aplicaciones" y "reducciones" transformes una expresión lambda hasta
llegar a un valor, independientemente del orden en que hagas las
transformaciones.

Si una misma expresión lambda, ante el mismo argumento da resultados
distintos, entonces el orden en que hagas su evaluación cambia el
resultado. Estaría incumpliendo el principio de transparencia referencial.

Si se encapsula una función con una clausura para mantener estados, los
resultados de la función podrían ser distintos ante los mismos argumentos.
No podemos sustituir la llamada a la función por su resultado, por lo que
se incumple la transparencia referencial. En realidad, solemos decir más
que la función tiene "efectos colaterales".

En haskell, no existen los "contextos" como los llamas. Todo son
"transformaciones" entre unos valores de entrada y de salida. Para mantener
"estados" se usan las "transformaciones monádicas", que no son "clausuras".
No se almacena ningún estado, sólo indicas de qué estado a qué estado
pasas, sin ninguna persistencia entre llamadas.

En cuanto a las características de programación funcional que pueda tener
python, muy pocos las usan o son conscientes de que las usan. Python, junto
con su librería estándar, es un compendio de conocimientos aplicados que
han sido traídos desde otros lenguajes. Mucho de lo que llamamos "modo
pythónico" de hacer las cosas no son otra cosa que transformaciones
funcionales con una teoría detrás que ignoramos mayormente: compresiones de
listas, tipos algebraicos, dataclases, ordenación por clave, etc, etc.En mi
opinión, hay mucho potencial en python que no se usa bien o se ignora que
está ahí.

Seguro que Guido hace bien en mantener un lenguaje python accesible para
todos y que no quiera liarla más con conceptos de programación funcional.
Pero me parece una pena.


Saludos.



El lun, 11 ene 2021 a las 21:18, Jose Luis (<jleahred en gmail.com>) escribió:

> Una pequeña observación.
>
> Güido ha explicado de forma brillante y coherente en alguna ocasión, que
> Python no es ni pretende ser "muy" funcional
>
> Los "closures" de Python (hay que matizar, porque cada uno define closure
> como le da la gana), capturan "cosas" (llámalo estado si quieres), OK
> Pero eso no va en contra de la transparencia referencial.
>
> Las lambdas de Haskell capturan "cosas" y es muy raro que rompan la
> transparencia referencial.
>
> De hecho, el concepto closure diría que viene del cálculo lambda (del
> genial "profe" de Turing, Alonzo Church), y simplificando, son funciones
> anónimas (aka lambdas) que capturan y tampoco rompen la transparencia
> referencial (es la gracia del cálculo lambda vs la máquina de Turing ;-)
>
> Una función lambda con un contexto difernte, es una función diferente. Si
> tú le pones el mismo nombre "mutando" o haces mutaciones del contexto...
> puedes romper la transparencia referencial, pero no es por el concepto de
> "closure" o captura
> Vamos, que si capturar "cosas" (aka contexto, aka estado, aka variables,
> aka "llámalo como quieras") violara la transparencia referencial, Haskell
> no sería muy funcional (ni el cálculo lambda)  ;-)
>
> Reitero que no tengo claro que forzar "mucho" la programación funcional en
> Python sea buena idea.
> Que yo lo opine, poco valor tiene, pero considero a Güido como un tipo
> coherente y muy inteligente, del que he aprendido un montón de cosas con
> sus reflexiones y explicaciones; y corregidme si me equivoco, pero diría
> que Güido no es partidario de "forzar" python con programación funcional
> (si fuera un tipo más serio y simpático, mandaría los enlaces de Güido al
> respecto, pero los tengo que buscar, estoy cansado y tampoco dispongo de
> tiempo en este momento)
>
>
> Saludos de un humilde amante de la programación funcional (amor no
> correspondido; ni me quiere la programación funcional, ni la imperativa,
> pero sigo dando guerra ;-)
>
> On Wed, Jan 6, 2021 at 5:31 PM Chema Cortes <pych3m4 en gmail.com> wrote:
>
>>
>> El mar, 5 ene 2021 a las 16:19, Jesus Cea (<jcea en jcea.es>) escribió:
>>
>>> On 4/1/21 11:18, Chema Cortes wrote:
>>> > La recursividad en python es muy limitada. Pero lo que viene a
>>> descubrir
>>> > es algo que se podría haber hecho mejor con generadores. En cuanto al
>>> > otro uso, sería una aplicación parcial de argumentos
>>> (functools.partial).
>>> >
>>> > Aún así, hay algoritmos recursivos que no son tan fácilmente
>>> > transcribibles en iterables.
>>>
>>> Más allá del uso chorras para convertir una función concreta de
>>> recursiva a iterativa, para mí lo interesante del artículo es el uso de
>>> "closures" para generar funciones personalizadas que se llevan su estado
>>> consigo. No todo necesita el coste de crear clases e instancias
>>> explícitas, no todo se puede solucionar con generadores y
>>> "functools.partial()" no proporciona estado mutable.
>>>
>>> El uso de "closures" explícitos me parece algo que vale la pena añadir a
>>> la caja de herramientas, siempre vigilando que no existe una forma más
>>> elegante de hacer algo concreto.
>>>
>>>
>> Aunque suene bien que las funciones mantengan su propio estado, nunca es
>> aconsejable que las funciones tengan efectos colaterales (violación de la transparencia
>> referencial <https://en.wikipedia.org/wiki/Referential_transparency>).
>>
>> Las clausuras son importantes y están en el fondo de muchos recursos como
>> pueden ser los *decoradores*. Pero es siempre posible crear un generador
>> (Iterable) en lugar de una función con clausura (Callable). La
>> diferencia es que los generadores están *protocolizados*,  con opciones
>> para poner fin a la iteración (StopIteration), para inyectar datos a la
>> clausura (método .send()) o para destruir el generador (GeneratorExit).
>> También se pueden usar en gran parte de la librería estándar, con las
>> funciones de itertools como las más potentes.
>>
>> Por comparar, la función de fibonacci como generador:
>>
>> from itertools import islice
>>
>> def fib():
>>     a, b = 1, 1
>>     while True:
>>         yield a
>>         a, b = b, a+b
>>
>> def fib_generator(n):
>>     return next(islice(fib(), n-1, None))
>>
>>
>> Si se compara, es casi el doble de rápida que la que viene en el
>> artículo, fib_closure.
>>
>> Saludos.
>>
>>
>> --
>> Hyperreals *R  "Quarks, bits y otras criaturas infinitesimales":
>> https://blog.ch3m4.org
>> Buscador Python Hispano: http://busca.ch3m4.org
>> <https://blog.ch3m4.org/pages/busqueda-python-es/>
>> _______________________________________________
>> Asociación Python España: http://www.es.python.org/
>> Python Madrid: http://www.python-madrid.es/
>> Madrid mailing list
>> Madrid en lists.es.python.org
>> https://lists.es.python.org/listinfo/madrid
>>
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <https://lists.es.python.org/pipermail/vigo/attachments/20210112/8f6f9c7c/attachment-0001.htm>


Más información sobre la lista de distribución Vigo