<div dir="ltr"><div></div><div>Una pequeña observación.</div><div><br></div><div>Güido ha explicado de forma brillante y coherente en alguna ocasión, que Python no es ni pretende ser "muy" funcional<br></div><div><br></div><div>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</div><div>Pero eso no va en contra de la transparencia referencial.</div><div><br></div><div>Las lambdas de Haskell capturan "cosas" y es muy raro que rompan la transparencia referencial.</div><div><br></div><div>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 ;-)<br></div><div><br></div><div>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</div><div>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) ;-)<br></div><div><br></div><div>Reitero que no tengo claro que forzar "mucho" la programación funcional en Python sea buena idea.</div><div>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)<br></div><div><br></div><div><br></div><div>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 ;-)<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jan 6, 2021 at 5:31 PM Chema Cortes <<a href="mailto:pych3m4@gmail.com">pych3m4@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif;font-size:large"></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El mar, 5 ene 2021 a las 16:19, Jesus Cea (<<a href="mailto:jcea@jcea.es" target="_blank">jcea@jcea.es</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 4/1/21 11:18, Chema Cortes wrote:<br>
> La recursividad en python es muy limitada. Pero lo que viene a descubrir <br>
> es algo que se podría haber hecho mejor con generadores. En cuanto al <br>
> otro uso, sería una aplicación parcial de argumentos (functools.partial).<br>
> <br>
> Aún así, hay algoritmos recursivos que no son tan fácilmente <br>
> transcribibles en iterables.<br>
<br>
Más allá del uso chorras para convertir una función concreta de <br>
recursiva a iterativa, para mí lo interesante del artículo es el uso de <br>
"closures" para generar funciones personalizadas que se llevan su estado <br>
consigo. No todo necesita el coste de crear clases e instancias <br>
explícitas, no todo se puede solucionar con generadores y <br>
"functools.partial()" no proporciona estado mutable.<br>
<br>
El uso de "closures" explícitos me parece algo que vale la pena añadir a <br>
la caja de herramientas, siempre vigilando que no existe una forma más <br>
elegante de hacer algo concreto.<br>
<br></blockquote><div><br></div><div><div style="font-family:georgia,serif;font-size:large" class="gmail_default">Aunque suene bien que las funciones mantengan su propio estado, nunca es aconsejable que las funciones tengan efectos colaterales (violación de la <a href="https://en.wikipedia.org/wiki/Referential_transparency" target="_blank">transparencia referencial</a>).<br></div><br></div><div></div><div><div style="font-family:georgia,serif;font-size:large" class="gmail_default">Las clausuras son importantes y están en el fondo de muchos recursos como pueden ser los <i>decoradores</i>. Pero es siempre posible crear un generador (<span style="font-family:monospace">Iterable</span>) en lugar de una función con clausura (<span style="font-family:monospace">Callable</span>). La diferencia es que los generadores están <i>protocolizados</i>, con opciones para poner fin a la iteración (<span style="font-family:monospace">StopIteration</span>), para inyectar datos a la clausura (método <span style="font-family:monospace">.send()</span>) o para destruir el generador (<span style="font-family:monospace">GeneratorExit</span>). También se pueden usar en gran parte de la librería estándar, con las funciones de itertools como las más potentes.<br></div><div style="font-family:georgia,serif;font-size:large" class="gmail_default"><br></div><div style="font-family:georgia,serif;font-size:large" class="gmail_default">Por comparar, la función de fibonacci como generador:</div><div style="font-size:large" class="gmail_default"><span style="font-family:monospace"><br></span></div><div class="gmail_default"><font size="2"><span style="font-family:monospace">from itertools import islice</span></font></div><div class="gmail_default"><font size="2"><span style="font-family:monospace"><br></span></font></div><div class="gmail_default"><font size="2"><span style="font-family:monospace">def fib():</span></font></div><div class="gmail_default"><font size="2"><span style="font-family:monospace"> a, b = 1, 1</span></font></div><div class="gmail_default"><font size="2"><span style="font-family:monospace"> while True:</span></font></div><div class="gmail_default"><font size="2"><span style="font-family:monospace"> yield a</span></font></div><div style="font-family:georgia,serif" class="gmail_default"><font size="2"><span style="font-family:monospace"> a, b = b, a+b</span><br></font></div></div><div><font size="2"><span style="font-family:monospace"></span></font></div><span class="gmail_default" style="font-family:georgia,serif;font-size:large"></span><pre><font size="2"><span id="gmail-m_-7213667193729054652gmail-7ce0">def fib_<span class="gmail_default">generator</span>(n):<br> <span class="gmail_default">return next(islice(fib(), n-1, None))</span></span></font></pre></div><div class="gmail_quote"><br></div><div class="gmail_quote"><div style="font-family:georgia,serif;font-size:large" class="gmail_default">Si se compara, es casi el doble de rápida que la que viene en el artículo, <span style="font-family:monospace">fib_closure</span>.</div><div style="font-family:georgia,serif;font-size:large" class="gmail_default"><br></div></div><div class="gmail_quote"><div style="font-family:georgia,serif;font-size:large" class="gmail_default">Saludos.</div><br><div><span style="font-family:georgia,serif"> </span></div></div>-- <br><div dir="ltr"><div dir="ltr"><div>Hyperreals *R "Quarks, bits y otras criaturas infinitesimales": <a href="https://blog.ch3m4.org" target="_blank">https://blog.ch3m4.org</a><br>Buscador Python Hispano: <a href="https://blog.ch3m4.org/pages/busqueda-python-es/" target="_blank">http://busca.ch3m4.org</a></div></div></div></div></div></div>
_______________________________________________<br>
Asociación Python España: <a href="http://www.es.python.org/" rel="noreferrer" target="_blank">http://www.es.python.org/</a><br>
Python Madrid: <a href="http://www.python-madrid.es/" rel="noreferrer" target="_blank">http://www.python-madrid.es/</a><br>
Madrid mailing list<br>
<a href="mailto:Madrid@lists.es.python.org" target="_blank">Madrid@lists.es.python.org</a><br>
<a href="https://lists.es.python.org/listinfo/madrid" rel="noreferrer" target="_blank">https://lists.es.python.org/listinfo/madrid</a><br>
</blockquote></div>