{"id":1565,"date":"2023-11-25T12:23:11","date_gmt":"2023-11-25T11:23:11","guid":{"rendered":"https:\/\/intsight.com\/?p=1565"},"modified":"2023-11-25T12:23:11","modified_gmt":"2023-11-25T11:23:11","slug":"secuencias","status":"publish","type":"post","link":"https:\/\/intsight.com\/index.php\/2023\/11\/25\/secuencias\/","title":{"rendered":"Secuencias"},"content":{"rendered":"<p><span style=\"font-variant:small-caps;font-size:107%;\">Esto es una<\/span> perogrullada: en un lenguaje de programaci\u00f3n funcional, las cosas se suelen hacer de forma diferente. Y probablemente escribir \u00abperogrullada\u00bb sea una pedanter\u00eda. Dejo el p\u00e1rrafo vivo por pereza, pero no me lo tenga en cuenta.<\/p>\n<h4>Factorial<\/h4>\n<p>Austra no pretende ser un lenguaje de programaci\u00f3n funcional. Ni siquiera pretende ser \u00abTuring-completo\u00bb. En alg\u00fan punto del camino, he pensado en dise\u00f1ar un lenguaje \u00abde verdad\u00bb, e incluso en saltarme la maquinaria de .NET para compilarlo a c\u00f3digo nativo directamente. Pero falta un poco para eso.<\/p>\n<p>De todas maneras, hay que intentar que se puedan hacer todas las cosas posibles en Austra. Por ejemplo, \u00bfc\u00f3mo calculas un factorial, si no tienes todav\u00eda funciones recursivas, y no quieres introducir bucles? Hasta ahora, la soluci\u00f3n era parecida a \u00e9sta:<\/p>\n<pre class=\"EnlighterJSRAW\">\nvec(10, i =&gt; i + 1).prod\n<\/pre>\n<p>No estamos definiendo una funci\u00f3n, sino que estamos usando un par\u00e1metro a dedo, pero funciona. Creamos un vector de 10 entradas, lo llenamos con los n\u00fameros del 1 al 10, y multiplicamos todos los elementos del vector. Incluso podemos \u00aboptimizar\u00bb un poco la expresi\u00f3n:<\/p>\n<pre class=\"EnlighterJSRAW\">\nvec(8, i =&gt; i + 2).prod * 2\n<\/pre>\n<p>Es absurdo dejar el <code>1<\/code> en el vector, y ya que tenemos diez elementos, en vez de dejarlos nueve, quito tambi\u00e9n el <code>2<\/code>. Eso lo hago porque s\u00e9 que internamente el producto mete los ocho elementos en dos registros  AVX y no tengo que manejar el elemento nuevo aparte. El problema es que, de todas maneras, estamos pidiendo memoria para el vector.<\/p>\n<p>En Austra 2.0 (que ya tiene soporte para .NET 8 y AVX512, dicho sea de paso), ya est\u00e1n implementadas las secuencias de valores reales, y puedes hacer esto otro, que es m\u00e1s natural:<\/p>\n<pre class=\"EnlighterJSRAW\">\nseq(2, 10).prod\n<\/pre>\n<p>La nueva clase se llama <a href=\"https:\/\/marteens.com\/austra\/library\/html\/d1757dd1-7bbd-4d90-88b9-cc034c5ad326.htm\" rel=\"noopener\" target=\"_blank\"><code>seq<\/code><\/a>, y es una copia descarada del dise\u00f1o de enumerables y LINQ (o de los streams de Java, o de las \u00ablist comprehensions\u00bb de tantos otros lenguajes funcionales). Ahora tenemos un <code>seq<\/code>, pero luego vendr\u00e1n <code>iseq<\/code> y <code>cseq<\/code>, para secuencias de enteros y complejos. Observe tambi\u00e9n que he acortado <code>vector<\/code> a <code>vec<\/code>, para usar <code>cvec<\/code> en vez de <code>complexvector<\/code>, y para que un futuro vector de enteros se pueda llamar <code>ivec<\/code> a secas.<\/p>\n<p>Las secuencias pueden hacer casi todas las cosas que hacen los vectores, y en la mayor\u00eda de los casos, generarlas es m\u00e1s sencillo: con el vector, usamos una funci\u00f3n lambda. Tambi\u00e9n permiten ahorrar c\u00f3digo porque aplican los mismos trucos que LINQ para objetos. Por ejemplo:<\/p>\n<pre class=\"EnlighterJSRAW\">\n-- Esta es una secuencia que divide el intervalo\n-- de 0 a 2*pi en 360 trozos.\n-- Multiplicamos cada n\u00famero por dos...\nseq(0, \u03c4, 360) * 2\n-- .. pero internamente, lo transformamos en esto:\nseq(0, 2\u03c4, 360)\n<\/pre>\n<h4>Recursividad eficiente<\/h4>\n<p>Y esto \u00faltimo todav\u00eda no est\u00e1 implementado, pero es bueno pensar en estas cosas antes de lanzarse a programarlas. \u00bfC\u00f3mo definir\u00edamos una funci\u00f3n para el factorial que fuese medianamente eficiente, pero usando recursividad? Lo que se suele hacer en un lenguaje funcional, pero con una notaci\u00f3n al estilo Austra:<\/p>\n<pre class=\"EnlighterJSRAW\">\ndef fact(n: int) =\n  let f = (n, acc: int) =>\n    if n = 1 then acc else f(n - 1, acc * n) in\n      f(n, 1)\n<\/pre>\n<p>El truco est\u00e1 en usar una funci\u00f3n auxiliar, que al estilo Austra ser\u00eda una lambda en una cl\u00e1usula <code>let<\/code>. La funci\u00f3n auxiliar es recursiva por la cola, por lo que el propio JIT de .NET la puede convertir en un bucle. La recursividad en lambdas va a ser problem\u00e1tica, porque estoy usando directamente Linq.Expressions para generar c\u00f3digo, pero hay un truco sencillo, que es el que voy a usar en las primeras pruebas: declarar una variable de tipo lambda, asignarle un puntero vac\u00edo, y a continuaci\u00f3n, asignarle una expresi\u00f3n lambda que ya podr\u00e1 usar la variable recursivamente. La alternativa es usar un <a href=\"https:\/\/en.wikipedia.org\/wiki\/Fixed-point_combinator\" rel=\"noopener\" target=\"_blank\">combinador Y<\/a>. Es un truco que viene, precisamente, del c\u00e1lculo lambda, sobre el que escribir\u00e9 en alg\u00fan momento. No es que sea c\u00f3modo o eficiente, pero es interesante.<\/p>\n<p>De todas maneras, me he dado cuenta, revisando la documentaci\u00f3n, que en F# hay que anunciar cuando una funci\u00f3n va a ser recursiva. Una alternativa que tengo que pensar es generar un \u00abm\u00e9todo din\u00e1mico\u00bb en estos casos, con el esfuerzo adicional de generar directamente el c\u00f3digo IL. Pero tengo ya experiencia de generar IL con <a href=\"https:\/\/freyalang.blogspot.com\/\" rel=\"noopener\" target=\"_blank\">Freya<\/a>, y puedo reutilizar c\u00f3digo.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Esto es una perogrullada: en un lenguaje de programaci\u00f3n funcional, las cosas se suelen hacer de forma diferente. Y probablemente escribir \u00abperogrullada\u00bb sea una pedanter\u00eda. Dejo el p\u00e1rrafo vivo por pereza, pero no me lo tenga en cuenta. Factorial Austra no pretende ser un lenguaje de programaci\u00f3n funcional. Ni siquiera pretende ser \u00abTuring-completo\u00bb. En alg\u00fan [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1567,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4,7],"tags":[73,90,91,89,26],"class_list":["post-1565","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c","category-fintech","tag-austra","tag-functional-programming","tag-lambda","tag-sequence","tag-vector"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/intsight.com\/wp-content\/uploads\/2023\/11\/seqs.png?fit=500%2C499&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1565","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/comments?post=1565"}],"version-history":[{"count":9,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1565\/revisions"}],"predecessor-version":[{"id":1576,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/posts\/1565\/revisions\/1576"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media\/1567"}],"wp:attachment":[{"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/media?parent=1565"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/categories?post=1565"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/intsight.com\/index.php\/wp-json\/wp\/v2\/tags?post=1565"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}