<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Angel "Java" Lopez : AjLisp</title><link>http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx</link><description>Tags: AjLisp</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Implementando Lenguajes de Programación en Javascript, JsConf Argentina</title><link>http://msmvps.com/blogs/lopez/archive/2012/05/21/implementing_2D00_programming_2D00_languages_2D00_in_2D00_javascript_2D00_jsconf_2D00_argentina.aspx</link><pubDate>Mon, 21 May 2012 10:47:19 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1810043</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1810043</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/05/21/implementing_2D00_programming_2D00_languages_2D00_in_2D00_javascript_2D00_jsconf_2D00_argentina.aspx#comments</comments><description>&lt;p&gt;Ayer, 20 de Mayo, tuve el gran gusto de presentar un tema que me gusta mucho, la implementación de lenguajes de programación, y en este caso, usando Javascript como lenguaje destino. Fue en la JSConf Argentina 2012:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://jsconf.com.ar/"&gt;http://jsconf.com.ar/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(Ya había escrito un post anunciando &lt;a href="http://msmvps.com/blogs/lopez/archive/2012/05/14/jsconf-argentina-javascript-en-buenos-aires.aspx"&gt;la conferencia&lt;/a&gt;) El día fue excelente, llena de interesantes charlas, muy bien organizada por &lt;a href="http://twitter.com/rauchg"&gt;@rauchg&lt;/a&gt; y su equipo (creo de &lt;a href="http://twitter.com/vulsai"&gt;@vulsai&lt;/a&gt;), tomé muchas notas, espero escribir uno o dos posts sobre el tema, en cuanto me recupere ;-) Mientras, pueden leer el post de &lt;a href="http://twitter.com/aijoona"&gt;@aijoona&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blog.aijoona.com/2012/05/21/jsconf-ar-2012-mi-resumen/"&gt;http://blog.aijoona.com/2012/05/21/jsconf-ar-2012-mi-resumen/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Como ejemplo de charla, vean la de WebGL para javascripters de &lt;a href="http://twitter.com/gerbille"&gt;@gerbille&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.slideshare.net/gerbille/webgl-para-javascripters"&gt;http://www.slideshare.net/gerbille/webgl-para-javascripters&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Este post contiene los enlaces y las implementaciones que visité y preparé para la charla, que tuvo poco de gráfico, y mucho, mucho de código. Debería comenzar a usar los lenguajes que presenté, para manejar temas gráficos en el cliente, por ejemplo WebGL, SVG, tal vez usar &lt;a href="http://d3js.org/"&gt;d3.js&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Mi presentación en &lt;a href="https://skydrive.live.com/redir?resid=9F903F3D6DB0C176!5746"&gt;mi Skydrive&lt;/a&gt; (nota: tengo que escribir la próxima presentación mía, supongo que será en el Ruby Meetup, en markdown y publicarla en HTML).&lt;/p&gt;  &lt;p&gt;Lista de lenguajes que compilan a Javascript    &lt;br /&gt;&lt;a href="https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS"&gt;https://github.com/jashkenas/coffee-script/wiki/List-of-languages-that-compile-to-JS&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The JavaScript World Domination Plan at 16 Years    &lt;br /&gt;&lt;a href="http://www.infoq.com/presentations/The-JavaScript-World-Domination-Plan-at-16-Years"&gt;http://www.infoq.com/presentations/The-JavaScript-World-Domination-Plan-at-16-Years&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Lisp as the Maxwell’s equations of software    &lt;br /&gt;&lt;a href="http://www.michaelnielsen.org/ddi/lisp-as-the-maxwells-equations-of-software/"&gt;http://www.michaelnielsen.org/ddi/lisp-as-the-maxwells-equations-of-software/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;A Conversation with Alan Kay    &lt;br /&gt;&lt;a href="http://queue.acm.org/detail.cfm?id=1039523"&gt;http://queue.acm.org/detail.cfm?id=1039523&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The Magnificent Seven    &lt;br /&gt;by Michael Fogus     &lt;br /&gt;&lt;a href="http://fogus.me/static/preso/magnificent7/#slide1"&gt;http://fogus.me/static/preso/magnificent7/#slide1&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;McCarthy&amp;#39;s Lisp in Python with macros    &lt;br /&gt;&lt;a href="https://github.com/fogus/lithp"&gt;https://github.com/fogus/lithp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The roots of Lisp    &lt;br /&gt;&lt;a href="http://www.paulgraham.com/rootsoflisp.html"&gt;http://www.paulgraham.com/rootsoflisp.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Presenté AjLisp en Javascript    &lt;br /&gt;&lt;a title="https://github.com/ajlopez/AjLispJs" href="https://github.com/ajlopez/AjLispJs"&gt;https://github.com/ajlopez/AjLispJs&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Comenté y mostré demo de AjLogo en Javascript    &lt;br /&gt;&lt;a title="https://github.com/ajlopez/AjLogoJs" href="https://github.com/ajlopez/AjLogoJs"&gt;https://github.com/ajlopez/AjLogoJs&lt;/a&gt;     &lt;br /&gt;Demo &lt;a title="http://ajlopez.github.com/AjLogoJs/demo.html" href="http://ajlopez.github.com/AjLogoJs/demo.html"&gt;http://ajlopez.github.com/AjLogoJs/demo.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Otras implementaciones de Logo en Javascript    &lt;br /&gt;&lt;a title="http://www.calormen.com/Logo/" href="http://www.calormen.com/Logo/"&gt;http://www.calormen.com/Logo/&lt;/a&gt;     &lt;br /&gt;&lt;a title="http://logo.twentygototen.org/" href="http://logo.twentygototen.org/"&gt;http://logo.twentygototen.org/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Recomendé ver a NetLogo &lt;a href="http://ccl.northwestern.edu/netlogo/"&gt;http://ccl.northwestern.edu/netlogo/&lt;/a&gt; (en Java) para ver hasta dónde ha llegado el tema.&lt;/p&gt;  &lt;p&gt;Hice correr el REPL y el compilador de Clojurescript    &lt;br /&gt;&lt;a href="https://github.com/clojure/clojurescript"&gt;https://github.com/clojure/clojurescript&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Presenté a la AjTalk VM en C#, y desde el año pasado compila Smalltalk a Javascript    &lt;br /&gt;&lt;a title="https://github.com/ajlopez/AjTalk" href="https://github.com/ajlopez/AjTalk"&gt;https://github.com/ajlopez/AjTalk&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Este año agregué AjTalk en Javascript, con VM en bytecodes, y ejecutor de métodos compilados con AjTalk    &lt;br /&gt;&lt;a title="https://github.com/ajlopez/AjTalkJs" href="https://github.com/ajlopez/AjTalkJs"&gt;https://github.com/ajlopez/AjTalkJs&lt;/a&gt;     &lt;br /&gt;Demo &lt;a title="http://ajlopez.github.com/AjTalkJs/demo.html" href="http://ajlopez.github.com/AjTalkJs/demo.html"&gt;http://ajlopez.github.com/AjTalkJs/demo.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Mostré una simple demo de clases Smalltalk compiladas a Javascript, que manejan google, y google.earth.&lt;/p&gt;  &lt;p&gt;Levanté Amber y comenté cómo en su definición de métodos ponen Javascript nativo   &lt;br /&gt;&lt;a href="http://amber-lang.net/"&gt;http://amber-lang.net/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Visité la página de Smalltalk S8, U8    &lt;br /&gt;&lt;a title="http://u8.smalltalking.net/" href="http://u8.smalltalking.net/"&gt;http://u8.smalltalking.net/&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://u8.smalltalking.net/browsecontributions.aspx"&gt;http://u8.smalltalking.net/browsecontributions.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;No pudimos ver las demos, justo en ese momento estuve sin conexión. Les comento algunos enlaces. Veamos dos:&lt;/p&gt;  &lt;p&gt;Hay una Smalltalk S8 Console (con una compilación de V8 preparada para levantar código st)   &lt;br /&gt;&lt;a title="http://u8.smalltalking.net/profile/smalltalking/125/index.html" href="http://u8.smalltalking.net/profile/smalltalking/125/index.html"&gt;http://u8.smalltalking.net/profile/smalltalking/125/index.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ver sus demos de Google Earth   &lt;br /&gt;&lt;a href="http://u8.smalltalking.net/contribution.aspx?contributionId=222"&gt;http://u8.smalltalking.net/contribution.aspx?contributionId=222&lt;/a&gt;    &lt;br /&gt;(exploren las clases, creo que eran Google, GoogleEarth, GoogleEarthObject, GEDemo, etc…)&lt;/p&gt;  &lt;p&gt;Mis posts sobre AjTalk, AjLisp, AjLogo implementations    &lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/category/ajtalk/"&gt;http://ajlopez.wordpress.com/category/ajtalk/&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/category/ajlisp/"&gt;http://ajlopez.wordpress.com/category/ajlisp/&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://ajlopez.wordpress.com/category/ajlogo/"&gt;http://ajlopez.wordpress.com/category/ajlogo/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx"&gt;http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjLogo/default.aspx"&gt;http://msmvps.com/blogs/lopez/archive/tags/AjLogo/default.aspx&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjTalk/default.aspx"&gt;http://msmvps.com/blogs/lopez/archive/tags/AjTalk/default.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Mis posts sobre Javascript   &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Javascript/default.aspx"&gt;http://msmvps.com/blogs/lopez/archive/tags/Javascript/default.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Les agrego algunos enlaces sobre ClojureScript, que no mencioné&lt;/p&gt;  &lt;p&gt;Introducing ClojureScript   &lt;br /&gt;&lt;a href="http://clojure.com/blog/2011/07/22/introducing-clojurescript.html"&gt;http://clojure.com/blog/2011/07/22/introducing-clojurescript.html&lt;/a&gt;    &lt;br /&gt;de &lt;a href="http://twitter.com/stuartsierra"&gt;@stuartsierra&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;ClojureScript Rationale   &lt;br /&gt;&lt;a href="https://github.com/clojure/clojurescript/blob/master/devnotes/cljs.org"&gt;https://github.com/clojure/clojurescript/blob/master/devnotes/cljs.org&lt;/a&gt;    &lt;br /&gt;de &lt;a href="http://twitter.com/stuarthalloway"&gt;@stuarthalloway&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Compiling Clojure to Javascript pt. 1 of n   &lt;br /&gt;&lt;a href="http://blog.fogus.me/2011/07/21/compiling-clojure-to-javascript-pt1/"&gt;http://blog.fogus.me/2011/07/21/compiling-clojure-to-javascript-pt1/&lt;/a&gt;    &lt;br /&gt;de &lt;a href="http://twitter.com/fogus"&gt;@fogus&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Ferret: An Experimental Clojure Compiler   &lt;br /&gt;&lt;a href="http://nakkaya.com/2011/06/29/ferret-an-experimental-clojure-compiler/"&gt;http://nakkaya.com/2011/06/29/ferret-an-experimental-clojure-compiler/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Los enlaces que me interesaron, leí, estudié para esta charla, o los tengo pendientes:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/clojurescript"&gt;http://delicious.com/ajlopez/clojurescript&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/javascript+parser"&gt;http://delicious.com/ajlopez/javascript+parser&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/javascript+compiler"&gt;http://delicious.com/ajlopez/javascript+compiler&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/javascript+smalltalk"&gt;http://delicious.com/ajlopez/javascript+smalltalk&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez    &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1810043" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjTalk/default.aspx">AjTalk</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Argentina/default.aspx">Argentina</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLogo/default.aspx">AjLogo</category></item><item><title>Ruby Buenos Aires Meetup Marzo 2012</title><link>http://msmvps.com/blogs/lopez/archive/2012/03/30/ruby-buenos-aires-meetup-marzo-2012.aspx</link><pubDate>Fri, 30 Mar 2012 11:59:16 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1808173</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1808173</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2012/03/30/ruby-buenos-aires-meetup-marzo-2012.aspx#comments</comments><description>&lt;p&gt;Ayer tuve el gusto de asistir a mi segunda meetup de Ruby acá en Buenos Aires. Fue en &lt;a href="http://argentina.enjoyurbanstation.com/es/"&gt;Urban Station&lt;/a&gt;, un buen lugar para trabajadores móviles: pueden ir con su notebook y trabajar en una mesita, con WiFi, enchufe, pagando por hora, o alquilar salones chicos de reuniones. La gente de Ruby Argentina consiguió una sala con proyector. Llegué a las 18:20 (empeza 18:30), y me encontré con Esteban, arquitecto, programador PHP, que estaba en Ruby. Mientras esperábamos, aproveché para preguntarle por qué se usa en Arquitectura, me enteré de Build Information Modeling, ver mis enlaces &lt;a href="http://delicious.com/ajlopez/bim"&gt;http://delicious.com/ajlopez/bim&lt;/a&gt;. Tenía algo con ver con la charla que iba a dar, sobre AjLisp en Ruby (ver mis posts &lt;a href="http://ajlopez.wordpress.com/category/ajlisp"&gt;http://ajlopez.wordpress.com/category/ajlisp&lt;/a&gt;), porque AutoCad tuvo desde siempre AutoLisp como lenguaje de base de programación.&lt;/p&gt;  &lt;p&gt;Poco a poco fue llegando más gente, como &lt;a href="http://twitter.com/soveran"&gt;@soveran&lt;/a&gt;, &lt;a href="http://twitter.com/maceto"&gt;@maceto&lt;/a&gt;, &lt;a href="http://twitter.com/inkel"&gt;@inkel&lt;/a&gt;, creo que llegó &lt;a href="http://twitter.com/etagwerker"&gt;@etagwerker&lt;/a&gt; pero no pude hablar con él. &lt;/p&gt;  &lt;p&gt;El primer disertante fue… moi ;-). Presenté AjLisp en Ruby, ver &lt;a href="https://github.com/ajlopez/AjLispRb"&gt;https://github.com/ajlopez/AjLispRb&lt;/a&gt;. Hace dos días, encontré esta presentación:&lt;/p&gt;  &lt;p&gt;How Emacs changed my life &lt;a href="http://www.slideshare.net/yukihiro_matz/how-emacs-changed-my-life"&gt;http://www.slideshare.net/yukihiro_matz/how-emacs-changed-my-life&lt;/a&gt; By Yukihiro &amp;quot;Matz&amp;quot;, Ruby creator&lt;/p&gt;  &lt;p&gt;Que me ayudó a poner la relación entre Lisp y Ruby. Conté algo de la historia de Lisp. Y destaqué que desarrollé AjLispRb usando TDD, desde el principio, para ir practicando y aprendiendo Ruby. Hice algunas demostraciones, mostrando rápidamente lambdas, define, closures y macros. Notablemente, cuando presenté que tiene una sintaxis tipo Java Dot Notation (ver &lt;a href="http://jscheme.sourceforge.net/jscheme/doc/javadot.html"&gt;http://jscheme.sourceforge.net/jscheme/doc/javadot.html&lt;/a&gt;) para acceder a objetos y clases Ruby, me preguntaron si esto anda en AjLisp:&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;(.require @Kernel &amp;quot;date”)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Consolas"&gt;(.today @Date)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;funcionó! ;-) Ni se me había ocurrido probarlo. En realidad, en vez de “@Kernel” puedo poner “pepe”, e igual termina invocando al método “global” require, tengo que investigar por qué. Jeje… AjLispRb tiene vida propia.&lt;/p&gt;  &lt;p&gt;Luego presentó Michel Martens, gran programador Ruby, &lt;a href="http://twitter.com/soveran"&gt;@soveran&lt;/a&gt;, y jugador de Go, ver &lt;a href="https://github.com/soveran"&gt;https://github.com/soveran&lt;/a&gt;, por ejemplo, vean su framework web Cuba &lt;a href="https://github.com/soveran/cuba"&gt;https://github.com/soveran/cuba&lt;/a&gt;. Presentó los elementos de uso de Rack, un tema que me interesa por su historia, relación con Python y otros. Ver mis enlaces &lt;a href="http://delicious.com/ajlopez/rack"&gt;http://delicious.com/ajlopez/rack&lt;/a&gt;. En un tiempo, quisiera preparar una charla corta sobre el tema, para algún Ruby Meetup u otro lugar.&lt;/p&gt;  &lt;p&gt;Y notablemente, presentó algo muy interesante, Bandicoot:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://bandilab.org/"&gt;http://bandilab.org/&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://www.readwriteweb.com/hack/2011/07/new-set-based-programming-language-bandicoot.php"&gt;http://www.readwriteweb.com/hack/2011/07/new-set-based-programming-language-bandicoot.php&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Su presentación en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://files.soveran.com/bandicoot/"&gt;http://files.soveran.com/bandicoot/&lt;/a&gt; (hecha con &lt;a href="https://github.com/nakajima/slidedown"&gt;https://github.com/nakajima/slidedown&lt;/a&gt;, ver &lt;a href="https://github.com/soveran/slidedown-skeleton"&gt;https://github.com/soveran/slidedown-skeleton&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;Interesante. Maneja conjuntos con operadores de álgebra relacional. Hmmm… interesante Code Kata para Pascual: implementar algo en C#, usando LINQ por debajo. Mis enlaces sobre el tema &lt;a title="http://delicious.com/ajlopez/set+programminglanguages " href="http://delicious.com/ajlopez/set+programminglanguages%20"&gt;http://delicious.com/ajlopez/set+programminglanguages &lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Michel lo usó en un proyecto. Vean que Bandicoot levanta un servidor al que se accede por HTTP, y en su lenguaje se programa los “puntos de entrada” que se exponen por ese servidor HTTP. El escribió un cliente Ruby &lt;a href="https://github.com/soveran/rel"&gt;https://github.com/soveran/rel&lt;/a&gt;. También comentó sobre su parser de command line &lt;a href="https://github.com/soveran/clap"&gt;https://github.com/soveran/clap&lt;/a&gt; (vean el uso de lambdas de Ruby ahí).&lt;/p&gt;  &lt;p&gt;Hubo otros temas que se trataron: el anuncio de Rails Girls&amp;#160; en Buenos Aires:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://railsgirls.com/buenosaires" href="http://railsgirls.com/buenosaires"&gt;http://railsgirls.com/buenosaires&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Se propuso hacer un Ruby Camp, reunirse para programar, ya sea en un lugar abierto, o en un bar, o en una casa. Se anunció que ya se comenzó a organizar la Ruby Conf de 2012.&lt;/p&gt;  &lt;p&gt;Se repartió “merchandising”, varios conseguimos una tarjeta de promoción de Code School &lt;a href="http://www.codeschool.com/"&gt;http://www.codeschool.com/&lt;/a&gt;. &lt;/p&gt;  &lt;p&gt;Un poco antes de las 21, se levantó la reunión que siguió con comida, bebida (supongo que agua mineral solamente ;-) en otros lugares de la zona de Palermo. Lo mío es la sopita de pollo, así que regresé a mi cubil principal.&lt;/p&gt;  &lt;p&gt;Felicitaciones a la gente de Ruby Argentina por tener una comunidad tan activa y abierta.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1808173" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Argentina/default.aspx">Argentina</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Ruby/default.aspx">Ruby</category></item><item><title>AjLisp en Ruby (2) Contexto con Nombres y Valores</title><link>http://msmvps.com/blogs/lopez/archive/2011/12/29/ajlisp_2D00_in_2D00_ruby_2D00_2_2D00_context_2D00_with_2D00_name_2D00_and_2D00_values.aspx</link><pubDate>Thu, 29 Dec 2011 10:20:56 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1804193</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1804193</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/12/29/ajlisp_2D00_in_2D00_ruby_2D00_2_2D00_context_2D00_with_2D00_name_2D00_and_2D00_values.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/12/03/ajlisp_2D00_on_2D00_ruby_2D00_1_2D00_structure_2D00_classes_2D00_and_2D00_tests.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Una de las primeras clases que implemente en &lt;a href="https://github.com/ajlopez/AjLispRb"&gt;AjLispRb&lt;/a&gt; es el ambiente (“environment”). Esta vez lo llamé contexto: un diccionaro donde guardar pares nombre/valor, los valores de los átomos con nombre. El código:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;module&lt;/span&gt; AjLisp
&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Context
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; initialize(parent = &lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;)
        @parent = parent
        @values = &lt;a style="color:#ff0000;" href="http://www.ruby-doc.org/docs/rdoc/1.9/classes/Hash.html"&gt;Hash&lt;/a&gt;.new
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; getValue(name)
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; @values.has_key?(name)
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; @values[name]
        &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
        
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; @parent != &lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; @parent.getValue(name)
        &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
        
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; setValue(name, value)
        @values[name] = value
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;La clase fue codificada usando TDD (Test-Driven Development), los primeros tests en &lt;strong&gt;test/test_context.rb&lt;/strong&gt;. Algunos tests:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_not_defined_is_nil
    context = AjLisp::Context.new
    assert_nil(context.getValue(:foo))
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_set_and_get_value
    context = AjLisp::Context.new
    context.setValue(:foo, &amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;)
    assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;, context.getValue(:foo))
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_get_value_from_parent
    parent = AjLisp::Context.new
    parent.setValue(:foo, &amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;)
    context = AjLisp::Context.new(parent)
    assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;, context.getValue(:foo))
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Inicialmente, yo usaba strings para los nombre, pero ahora estoy usando los símbolos de Ruby como &lt;strong&gt;:foo&lt;/strong&gt;. Tengo un test que asegura la independencia de los valores del contexto padre y del hijo:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_override_value_from_parent
    parent = AjLisp::Context.new
    parent.setValue(:foo, &amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;)
    context = AjLisp::Context.new(parent)
    context.setValue(:foo, &amp;quot;&lt;span style="color:#8b0000;"&gt;bar2&lt;/span&gt;&amp;quot;)
    assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;bar2&lt;/span&gt;&amp;quot;, context.getValue(:foo))
    assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;, parent.getValue(:foo))
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Cada contexto puede tener un contexto padre. Hay un contexto “tope”, definido &lt;strong&gt;lib/ajlisp.rb&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;module&lt;/span&gt; AjLisp
@context = Context.new
@context.setValue :quote, FPrimitiveQuote.instance
@context.setValue :first, PrimitiveFirst.instance
@context.setValue :rest, PrimitiveRest.instance
@context.setValue :cons, PrimitiveCons.instance
@context.setValue :list, PrimitiveList.instance
@context.setValue :lambda, FPrimitiveLambda.instance
@context.setValue :flambda, FPrimitiveFLambda.instance
@context.setValue :mlambda, FPrimitiveMLambda.instance
@context.setValue :let, FPrimitiveLet.instance
@context.setValue :define, FPrimitiveDefine.instance
@context.setValue :&lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;, FPrimitiveDo.instance
@context.setValue :&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;, FPrimitiveIf.instance
@context.setValue :definef, FPrimitiveDefinef.instance
@context.setValue :definem, FPrimitiveDefinem.instance
@context.setValue :+, PrimitiveAdd.instance
@context.setValue :-, PrimitiveSubtract.instance
@context.setValue :*, PrimitiveMultiply.instance
@context.setValue :/, PrimitiveDivide.instance
&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;.context
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; @context
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#008000;"&gt;# ...&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Los nuevos contexts son creado por varias primitivas. En el comienzo, existe el contexto tope definido arriba, como:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisprb02.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Si tenemos que definir una función que retorna el segundo elemento de una lista, podemos usar la primitiva define:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font size="3" face="Consolas"&gt;(define second (a) (first (rest a)))&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ahora tenemos en el contexto tope una nueva entrada para &lt;strong&gt;second&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisprb03.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;El contexto tope tiene ahí en esa nueva entrada el valor que representa un lambda&amp;#160; (&lt;strong&gt;lambda (a) (first (rest a))&lt;/strong&gt;&amp;#160; (en realidad, debería aclarar que se guarda el resultado de haber evaluado el lambda, que es un closure (clausura) pero ya llegaremos al tema en próximo post).&lt;/p&gt;

&lt;p&gt;Cuando invocamos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font size="3" face="Consolas"&gt;(second (quote (one two three)))&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;un nuevo contexto se crea, con su padre apuntando al contexto tope (de nuevo, es algo más complejo, veremos clausuras). Ese nuevo contexto tiene un par nombre/valor:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisprb04.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Este contexto es descartado LUEGO de esta evaluaciónThat de &lt;strong&gt;second&lt;/strong&gt;&amp;#160; (puede sobrevivir indirectamente si luego de la evaluación quedó referenciado por una clausura). Cuando definimos un valor simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font size="3" face="Consolas"&gt;(define one 1)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;el contexto tope es modificado, para tener un nuevo par nombre/valor:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisprb05.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Próximos temas: primitivas y formas especiales, su invocación, clausuras, macros, e invocación de métodos nativos de Ruby.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1804193" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Ruby/default.aspx">Ruby</category></item><item><title>AjLisp en Ruby (1) Estructura, Clases y Tests</title><link>http://msmvps.com/blogs/lopez/archive/2011/12/03/ajlisp_2D00_on_2D00_ruby_2D00_1_2D00_structure_2D00_classes_2D00_and_2D00_tests.aspx</link><pubDate>Sat, 03 Dec 2011 10:06:58 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1803194</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1803194</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/12/03/ajlisp_2D00_on_2D00_ruby_2D00_1_2D00_structure_2D00_classes_2D00_and_2D00_tests.aspx#comments</comments><description>&lt;p&gt;Estoy aprendiendo y practicando Ruby, y como es costumbre, lo hago escribiendo algo interesante para mí: el intérprete AjLisp (hace unos meses lo &lt;a href="http://msmvps.com/blogs/lopez/archive/2011/09/06/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_3_2D00_define_2D00_lambda_2D00_and_2D00_closures.aspx"&gt;implementé en Javascript&lt;/a&gt;). TDD es mi amigo: escribo un test, lo ejecuto en rojo, codifico para pasarlo a verde, refactorear, y así sigue. El código de este nuevo intérprete, trabajo en progreso, en:&lt;/p&gt;  &lt;p&gt;&lt;a href="https://github.com/ajlopez/AjLispRb"&gt;https://github.com/ajlopez/AjLispRb&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Inicialmente (pueden ver los logs) escribí todo en un solo archivo (código y tests), siguiendo el simple y claro ejemplo:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://kanemar.com/2006/03/04/screencast-of-test-driven-development-with-ruby-part-1-a-simple-example/" href="http://kanemar.com/2006/03/04/screencast-of-test-driven-development-with-ruby-part-1-a-simple-example/"&gt;http://kanemar.com/2006/03/04/screencast-of-test-driven-development-with-ruby-part-1-a-simple-example/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Vean que Ruby tiene un paquete ‘test/unit’ que ya viene en su instalación, listo para usar. Despues de algo de “research”, dividí el archivo en código de producción y código de pruebas. Quiero llegar a armar una gema (un paquete Ruby, distribuido por el utilitario gems), así que estudié los primeros pasos del tutorial:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://guides.rubygems.org/"&gt;http://guides.rubygems.org/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Tengo pendiente de leer y estudiar:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://speakerdeck.com/u/pat/p/cut-polish-a-guide-to-crafting-gems"&gt;http://speakerdeck.com/u/pat/p/cut-polish-a-guide-to-crafting-gems&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html"&gt;http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Así que mi código aún no es una gema. Pero va teniendo la estructura de una:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisprb01.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El directorio &lt;strong&gt;lib&lt;/strong&gt; contiene un solo archivo &lt;strong&gt;ajlisp.rb&lt;/strong&gt;:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/list.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/named_atom.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/context.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/string_source.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/token.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/lexer.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/parser.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive_first.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive_rest.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive_cons.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive_list.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive_closure.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive_quote.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive_lambda.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive_flambda.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive_let.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive_closure.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/fprimitive_define.rb&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp/primitive_add.rb&amp;#39;
&lt;span style="color:#0000ff;"&gt;module&lt;/span&gt; AjLisp
@context = Context.new
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;quote&lt;/span&gt;&amp;quot;, FPrimitiveQuote.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;first&lt;/span&gt;&amp;quot;, PrimitiveFirst.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;rest&lt;/span&gt;&amp;quot;, PrimitiveRest.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;cons&lt;/span&gt;&amp;quot;, PrimitiveCons.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;list&lt;/span&gt;&amp;quot;, PrimitiveList.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;lambda&lt;/span&gt;&amp;quot;, FPrimitiveLambda.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;flambda&lt;/span&gt;&amp;quot;, FPrimitiveFLambda.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;let&lt;/span&gt;&amp;quot;, FPrimitiveLet.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;define&lt;/span&gt;&amp;quot;, FPrimitiveDefine.instance
@context.setValue &amp;quot;&lt;span style="color:#8b0000;"&gt;+&lt;/span&gt;&amp;quot;, PrimitiveAdd.instance
&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;.context
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; @context
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;.evaluate(context, item)
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; item.is_a? List &lt;span style="color:#0000ff;"&gt;or&lt;/span&gt; item.is_a? NamedAtom
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; item.evaluate(context)
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
        
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; item	
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Escribí algunas primitivas (formas normales, y formas especiales: estas últimas no evalúan sus parámetros antes de su aplicación, ejemplos: &lt;strong&gt;quote&lt;/strong&gt; y&lt;strong&gt; define&lt;/strong&gt;). Noten que los archivos adicionales los puse en un subdirectorio &lt;strong&gt;ajlisp&lt;/strong&gt; dentro de &lt;strong&gt;lib&lt;/strong&gt;, ¿por qué? Porque cuando este código sea instalado como una gema, todo el directorio &lt;strong&gt;lib&lt;/strong&gt; estará disponible para &lt;strong&gt;require&lt;/strong&gt;, y si hubiera un archivo ahí, se podría hacer &lt;strong&gt;require(‘elarchivo’)&lt;/strong&gt;. Es por eso que los archivos adicionales a &lt;strong&gt;ajlisp.rb&lt;/strong&gt; se colocan en otro lado, evitando colisión de nombres. Se recomienda colocarlos debajo de &lt;strong&gt;lib&lt;/strong&gt; (vean el código de gemas que tienen en su instalación de Ruby, o vean ejemplos en GitHub).&lt;/p&gt;

&lt;p&gt;El el directorio &lt;strong&gt;test&lt;/strong&gt; hay un archivo &lt;strong&gt;test.rb &lt;/strong&gt;que incluye a los otros archivos de tests:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;&lt;span style="color:#00008b;"&gt;test&lt;/span&gt;/unit&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_list.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_named_atom.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_context.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_string_source.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_token.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_lexer.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_parser.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_primitive_first.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_primitive_rest.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_primitive_cons.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_primitive_list.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_primitive_closure.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_primitive_add.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_fprimitive_quote.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_fprimitive_lambda.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_fprimitive_let.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_fprimitive_closure.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_fprimitive_flambda.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_fprimitive_define.rb&lt;/span&gt;&amp;quot;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;quot;&lt;span style="color:#8b0000;"&gt;test_evaluate&lt;/span&gt;&amp;quot;
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Pueden ejecutar los tests desde la línea de comando:&lt;/p&gt;

&lt;p&gt;&lt;font size="3" face="Consolas"&gt;ruby –Ilib;test test\test.rb&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;En Windows, dejé el archivo &lt;strong&gt;runtest.cmd&lt;/strong&gt; conteniendo esta línea. Los parámetros &lt;strong&gt;–Ilib;test&lt;/strong&gt; le indican a Ruby que incluya los directorios lib y test para cuando tenga que resolver un &lt;strong&gt;require&lt;/strong&gt;. De esta forma evito poner directorios explícitos (o usar __FILE__) en los &lt;strong&gt;require&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Algo de tests:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;&lt;span style="color:#00008b;"&gt;test&lt;/span&gt;/unit&amp;#39;
&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; TestList &amp;lt; Test::Unit::TestCase
&lt;span style="color:#008000;"&gt;#...    &lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_create_with_first
        list = AjLisp::List.new(&amp;quot;&lt;span style="color:#8b0000;"&gt;foo&lt;/span&gt;&amp;quot;)
        assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;foo&lt;/span&gt;&amp;quot;, list.first)
        assert_nil(list.rest)
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_create_with_first_and_rest
        rest = AjLisp::List.new(&amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;)
        list = AjLisp::List.new(&amp;quot;&lt;span style="color:#8b0000;"&gt;foo&lt;/span&gt;&amp;quot;, rest)
        assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;foo&lt;/span&gt;&amp;quot;, list.first)
        assert_not_nil(list.rest)
        assert_equal(&amp;quot;&lt;span style="color:#8b0000;"&gt;bar&lt;/span&gt;&amp;quot;, list.rest.first)
        assert_nil(list.rest.rest)
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_create_from_array
        list = AjLisp::List.make [1, &amp;quot;&lt;span style="color:#8b0000;"&gt;a&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span style="color:#8b0000;"&gt;foo&lt;/span&gt;&amp;quot;]
        assert_not_nil list
        assert_equal 1, list.first
        assert_equal &amp;quot;&lt;span style="color:#8b0000;"&gt;a&lt;/span&gt;&amp;quot;, list.rest.first
        assert_equal &amp;quot;&lt;span style="color:#8b0000;"&gt;foo&lt;/span&gt;&amp;quot;, list.rest.rest.first
        assert_nil list.rest.rest.rest
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#008000;"&gt;#..&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Cada lista en AjLisp es un objeto de esta clase, &lt;strong&gt;list.rb&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;module&lt;/span&gt; AjLisp
&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; List
    attr_reader :first
    attr_reader :rest
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; initialize(first=&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;, rest=&lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;)
        @first = first
        @rest = rest
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; evaluate(context)
        form = AjLisp::evaluate(context, @first)
        form.evaluate(context, &lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;)
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;self&lt;/span&gt;.make(array)
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; array &lt;span style="color:#0000ff;"&gt;and&lt;/span&gt; array.length &amp;gt; 0
            first = array.shift
            
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; first.is_a? &lt;span style="color:#00008b;"&gt;Array&lt;/span&gt;
                first = make(first)
            &lt;span style="color:#0000ff;"&gt;elsif&lt;/span&gt; first.is_a? Symbol
                first = NamedAtom.new first.to_s
            &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
                        
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; List.new first, make(array)
        &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt; 
        
        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;nil&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Los méteodos de acceso &lt;strong&gt;first&lt;/strong&gt; y &lt;strong&gt;rest&lt;/strong&gt; son de sólo lectura. Gracias a la naturaleza no tipada de Ruby (facilidad que también encontré en la implementación de Javascript) la implementación de este intérprete es directa, sin mayor “ceremonia de código”. &lt;/p&gt;

&lt;p&gt;En mis nuevos tests, ahora incluye el código DENTRO del módulo &lt;strong&gt;AjLisp&lt;/strong&gt;, así me evito de escribir el prefijo &lt;strong&gt;AjLisp:: &lt;/strong&gt;antes de referenciar a una clase:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;ajlisp&amp;#39;
&lt;span style="color:#00008b;"&gt;require&lt;/span&gt; &amp;#39;&lt;span style="color:#00008b;"&gt;test&lt;/span&gt;/unit&amp;#39;
&lt;span style="color:#0000ff;"&gt;module&lt;/span&gt; AjLisp
&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; TestLexer &amp;lt; Test::Unit::TestCase
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_get_atom_token
        source = StringSource.new &amp;quot;&lt;span style="color:#8b0000;"&gt;atom&lt;/span&gt;&amp;quot;
        lexer = Lexer.new source
        token = lexer.nextToken
        
        assert_not_nil token
        assert_equal &amp;quot;&lt;span style="color:#8b0000;"&gt;atom&lt;/span&gt;&amp;quot;, token.value
        assert_equal TokenType::ATOM, token.type
        assert_nil lexer.nextToken
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;def&lt;/span&gt; test_get_atom_token_with_spaces
        source = StringSource.new &amp;quot;&lt;span style="color:#8b0000;"&gt;  atom   &lt;/span&gt;&amp;quot;
        lexer = Lexer.new source
        token = lexer.nextToken
        
        assert_not_nil token
        assert_equal &amp;quot;&lt;span style="color:#8b0000;"&gt;atom&lt;/span&gt;&amp;quot;, token.value
        assert_equal TokenType::ATOM, token.type
        assert_nil lexer.nextToken
    &lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;span style="color:#008000;"&gt;#...&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Próximos tópicos: algunos detalles de implementación, primitives vs fprimitives, contexto (ambiente anidado con pares nombre/valor), lambdas y closures, el lexer y el parser.&lt;/p&gt;

&lt;p&gt;Próximos pasos: completar las primitivas (let, letrec, definef, do, if…), macro (mlambda, definem, expansión de macros…)&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1803194" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx">Programaci&amp;#243;n Funcional</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Ruby/default.aspx">Ruby</category></item><item><title>AjLisp en Javascript (Parte 3) Define, Lambda y Closures</title><link>http://msmvps.com/blogs/lopez/archive/2011/09/06/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_3_2D00_define_2D00_lambda_2D00_and_2D00_closures.aspx</link><pubDate>Tue, 06 Sep 2011 11:05:08 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1799020</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1799020</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/09/06/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_3_2D00_define_2D00_lambda_2D00_and_2D00_closures.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/08/31/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_list_2D00_evaluation_2D00_form_2D00_and_2D00_special_2D00_forms.aspx"&gt;Anterior Post&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Veamos la definición de nuevas formas en AjLisp, mi intérprete Lisp escrito en Javascript (&lt;a href="https://github.com/ajlopez/AjLispJs"&gt;github repository&lt;/a&gt;). Un forma especial clave en AjLisp es la define:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; defineForm = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SpecialForm();
defineForm.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list, env)
{
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;name&lt;/span&gt; = list.first().&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;();
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; value = list.rest().first();
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; body = list.rest().rest();
		
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (isNil(body)) {
		value = evaluate(value, env);
	}
	&lt;span style="color:#0000ff;"&gt;else&lt;/span&gt; {
		value = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Closure(value, env, body);
	}		
		
	environment[&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;] = value;
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; value;
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Se puede usar para definir datos simples globales. Mis primeros tests:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;test(&amp;quot;&lt;span style="color:#8b0000;"&gt;Evaluate Simple Expression with Atoms&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() {
	&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(define one 1)&lt;/span&gt;&amp;quot;);
	&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(define two 2)&lt;/span&gt;&amp;quot;);
	&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(define three 3)&lt;/span&gt;&amp;quot;);
	equal(&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;one&lt;/span&gt;&amp;quot;), 1);
	equal(&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(quote one)&lt;/span&gt;&amp;quot;).asString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;one&lt;/span&gt;&amp;quot;);
	equal(&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(list one two three)&lt;/span&gt;&amp;quot;).asString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;(1 2 3)&lt;/span&gt;&amp;quot;);
	equal(&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(first (list one two three))&lt;/span&gt;&amp;quot;), 1);
	equal(&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(rest (list one two three))&lt;/span&gt;&amp;quot;).asString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;(2 3)&lt;/span&gt;&amp;quot;);
	equal(&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(&amp;quot;&lt;span style="color:#8b0000;"&gt;(cons one (list two three))&lt;/span&gt;&amp;quot;).asString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;(1 2 3)&lt;/span&gt;&amp;quot;);
});
		&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Pero define está preparada también para recibir tres parámetros:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;(define mapfirst (fn lst)
  (&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (nilp lst)
    nil
    (cons
      (fn (first lst))
      (mapfirst fn (rest lst))
    )
  )
)
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;El primer parámetro es el nombre de la propiedad a definir en el ambiente (environment) global. El segundo parámetro es una lista de parámetros. El tercero es la forma a aplicar. Entonces, define se puede usar para definir nuevas funciones, formas. Es equivalente a&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;(define mapfirst (lambda (fn lst)
    (&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (nilp lst)
      nil
      (cons
        (fn (first lst))
        (mapfirst fn (rest lst))
      )
    )
  )
)
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Vean el lambda. Es una forma especial:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; lambdaForm = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SpecialForm();
lambdaForm.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list, env)
{
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; argnames = list.first();
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; body = list.rest();
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Closure(argnames, env, body);
}
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Tanto define (con tres parámetros) como lambda terminan creando un Closure. La clausura recibe una lista de nombres de argumentos, un ambiente (closure environment) y un cuerpo. Entonces, cuando un closure se evalúa:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; Closure(argnames, closureenv, body) {
	body = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; List(doForm, body);
	
	&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(args, environment) {
		&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; newenv = makeEnvironment(argnames, args, closureenv);
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; evaluate(body, newenv);
	};
}
	
Closure.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.evaluate = Form.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.evaluate;
Closure.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.apply = Form.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.apply;
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;La parta clave es el .eval: la evalucación de closure emplea un nuevo environment, basado NO EN EL ACTUAL, sino en el closureenv, el ambiente recibido en el constructor cuando la clausura fue creada. Esta es una típica implementación en un intérprete Lisp.&lt;/p&gt;

&lt;p&gt;Próximos temas a discutir en posts: flambda, mlambda, evaluación de macros, y el parser.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1799020" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category></item><item><title>AjLisp en Javascript (Parte 2) Evaluación de Listas, Formas y Formas Especiales</title><link>http://msmvps.com/blogs/lopez/archive/2011/08/31/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_list_2D00_evaluation_2D00_form_2D00_and_2D00_special_2D00_forms.aspx</link><pubDate>Wed, 31 Aug 2011 11:11:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1798602</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1798602</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/08/31/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_list_2D00_evaluation_2D00_form_2D00_and_2D00_special_2D00_forms.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/08/20/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_atoms_2D00_lists_2D00_and_2D00_tdd.aspx"&gt;Anterior Post&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/09/06/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_3_2D00_define_2D00_lambda_2D00_and_2D00_closures.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En el anterior post present&amp;eacute; la estructura y creaci&amp;oacute;n de &amp;aacute;tomos y listas. Pero &amp;iquest;C&amp;oacute;mo se eval&amp;uacute;a una lista en AjLisp? Como en otras implementaciones de Lisp, la cabeza de la lista apunta a algo (lo que se llama una forma o forma especial) que se aplica al resto de los elementos. Este es el comienzo del proceso de evaluaci&amp;oacute;n de una lista:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;List.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.evaluate = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(environment) 
{
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; form = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.first().evaluate(environment);		
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; form.apply(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, environment);
}	
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;El primer elemento debe ser un elemento que evaluado, da un objecto con un .apply como m&amp;eacute;etodo. Hay dos clases de formas: las normales y las especiales. La implementaci&amp;oacute;n de Form:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; Form() {
}
Form.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.evaluate = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(environment) { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;; }
Form.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.apply = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(list, environment) 
{ 
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (isNil(list)) &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list, environment);
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; rest = list.rest();
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (rest != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
        rest = rest.evaluateList(environment);
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(rest, environment); 
}&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;La implementaci&amp;oacute;n de las especiales:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; SpecialForm() {
}
SpecialForm.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.evaluate = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(environment) { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;; }
SpecialForm.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.apply = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(list, environment) 
{ 
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (isNil(list)) &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list, environment);
    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list.rest(), environment);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;iquest;Notan la diferencia? Los elementos del resto de la lista SON EVALUADOS en una forma normal. Al contrario, una forma especial no los eval&amp;uacute;a. &amp;iquest;Por qu&amp;eacute; esa diferencia? Las formas especiales son &amp;ldquo;primitivas&amp;rdquo; como (if &amp;lt;cond&amp;gt; &amp;lt;then&amp;gt; &amp;lt;else&amp;gt;&amp;hellip;) donde las partes &amp;lt;then&amp;gt; &amp;lt;else&amp;gt;&amp;hellip; pueden evaluarse o no bajo el control de la forma especial. Vean:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.nhplace.com/kent/Papers/Special-Forms.html"&gt;Special Forms in Lisp&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Special forms are those expressions in the Lisp language which do not follow normal rules for evaluation. Some such forms are necessary as primitives of the language, while others may be desirable in order to improve readability, control the evaluation environment, implement abstraction and modularity, affect the flow of control, allow extended scoping mechanisms, define functions which accept a variable number of arguments, or achieve greater efficiency. There exist several long-standing mechanisms for specifying the definition of special forms: FEXPR&amp;#39;s, NLAMBDA&amp;#39;s, and MACRO&amp;#39;s. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;iquest;Ejemplos de Form? Los escrib&amp;iacute; usando instancias, redefiniendo su m&amp;eacute;todo eval:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; listForm = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Form();
listForm.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list) 
{
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; list;
}
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; nilpForm = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Form();
nilpForm.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list) 
{
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (isNil(list))
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
		
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; isNil(list.first());
}
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; listpForm = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Form();
listpForm.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list) 
{
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (isNil(list))
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;;
		
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; isList(list.first());
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Un ejemplo de forma especial, el &amp;lsquo;if&amp;rsquo;:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; ifForm = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; SpecialForm();
ifForm.&lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;eval&lt;/span&gt;(list, env)
{
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; cond = evaluate(list.first(), env);
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; then = list.rest().first();
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; elsebody = list.rest().rest();
	
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (!isNil(cond) &amp;amp;&amp;amp; cond != &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;)
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; evaluate(then, env);
	&lt;span style="color:#0000ff;"&gt;while&lt;/span&gt; (!isNil(elsebody)) 
	{
		result = evaluate(elsebody.first(), env);
		elsebody = elsebody.rest();
	}
	
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; result;			
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Se exponen en el enviroment global:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#008000;"&gt;// Environment&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; environment = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Environment();
environment.list = listForm;
environment.first = firstForm;
environment.rest = restForm;
environment.cons = consForm;
environment[&amp;#39;&lt;span style="color:#0000ff;"&gt;do&lt;/span&gt;&amp;#39;] = doForm;
environment[&amp;#39;&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;&amp;#39;] = ifForm;
&lt;span style="color:#008000;"&gt;// more settings in environment&lt;/span&gt;
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Temas para pr&amp;oacute;ximos posts: environments, closures, lambdas, macros, el parser y TDD.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1798602" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx">Programaci&amp;#243;n Funcional</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category></item><item><title>AjLisp en Javascript (Parte 1) Atomos, Listas y TDD</title><link>http://msmvps.com/blogs/lopez/archive/2011/08/20/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_atoms_2D00_lists_2D00_and_2D00_tdd.aspx</link><pubDate>Sat, 20 Aug 2011 10:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1797930</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1797930</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2011/08/20/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_atoms_2D00_lists_2D00_and_2D00_tdd.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/08/31/ajlisp_2D00_in_2D00_javascript_2D00_part_2D00_1_2D00_list_2D00_evaluation_2D00_form_2D00_and_2D00_special_2D00_forms.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Estoy reescribiendo &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx"&gt;mi int&amp;eacute;rprete AjLisp&lt;/a&gt; usando Javascript. Pienso que un int&amp;eacute;rprete Lisp es un buen proyecto para aprender un lenguaje: simple, acotado pero no trivial. Nunca hubiera comenzado este proyecto sin usar &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx"&gt;TDD (Test-Driven Development)&lt;/a&gt;: Javascript es muy din&amp;aacute;mico y las herramientas que estoy usando (el browser, editor de texto) son limitadas. Sin la ayuda de TDD este proyecto hubiera sido dif&amp;iacute;cil de desarrollar. TDD me divierte, avances en peque&amp;ntilde;os pasos y me ayuda a explorar e implementar buen dise&amp;ntilde;o.&lt;/p&gt;
&lt;p&gt;El c&amp;oacute;digo (con un parse, varias formas primitivas implementadas, algo de proceso de macros, trabajo en progreso) est&amp;aacute; en GitHub:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ajlopez/AjLispJs" title="https://github.com/ajlopez/AjLispJs"&gt;https://github.com/ajlopez/AjLispJs&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;El c&amp;oacute;digo reside en un solo archivo: &lt;a href="https://github.com/ajlopez/AjLispJs/blob/master/src/ajlisp.js" title="https://github.com/ajlopez/AjLispJs/blob/master/src/ajlisp.js"&gt;https://github.com/ajlopez/AjLispJs/blob/master/src/ajlisp.js&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Estoy usando &lt;a href="http://msmvps.com/blogs/lopez/archive/2011/07/12/tdd_2D00_with_2D00_javascript_2D00_and_2D00_qunit.aspx"&gt;QUnit para los tests&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlispjs01.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;La implementaci&amp;oacute;n usa el patr&amp;oacute;n namespace:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;AjLisp = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() {
&lt;span style="color:#008000;"&gt;// ...&lt;/span&gt;
}();
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;El namespace es el resultado de evaluar una funci&amp;oacute;n. Esta funci&amp;oacute;n retorna un objeto con los miembros p&amp;uacute;blicos que quiero exponer del namespace:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; {
	&lt;span style="color:#008000;"&gt;// Classes&lt;/span&gt;
	List: List,
	Environment: Environment,
	Atom: Atom,
	Closure: Closure,
	Lexer: Lexer,
	TokenType: TokenType,
	Parser: Parser,
	
	&lt;span style="color:#008000;"&gt;// Functions&lt;/span&gt;
	makeList: makeList,
	isAtom: isAtom,
	isList: isList,
	isNil: isNil,
	asString: asString,
	evaluate: evaluate,
	
	&lt;span style="color:#008000;"&gt;// Top Environment&lt;/span&gt;
	environment: environment
}&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Como es usual, un int&amp;eacute;rprete Lisp debe soportar listas y &amp;aacute;tomos. C&amp;oacute;digo parcial de mi implementaci&amp;oacute;n de lista:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; List(first, rest) {
	&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; getFirst() {
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; first;
	}
	
	&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; getRest() {
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; rest;
	}
	
	&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.first = getFirst;
	&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.rest = getRest;
}
List.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.isAtom = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;; }
List.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.isList = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;; }
List.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.evaluate = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(environment) 
{
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; form = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.first().evaluate(environment);		
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; form.apply(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;, environment);
}	
&lt;span style="color:#008000;"&gt;// ...&lt;/span&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Noten que first y rest est&amp;aacute;n encapsuladas en el closure del constructor. Son inmutables y puede accederse solamente desde funciones alist.first() y alist.last(). Deber&amp;iacute;a evaluar el impacto de usar un closure en la construcci&amp;oacute;n de una lista. Pero parece que es relativamente liviano.&lt;/p&gt;
&lt;p&gt;La implementaci&amp;oacute;n de Atom es simple:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; Atom(&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;) {
	&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.evaluate = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(environment) {
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; environment.getValue(&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;);
	};
	
	&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;; };
}
Atom.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.isAtom = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;; }
Atom.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.isList = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;; }
Atom.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.asString = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() { &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;(); }
Atom.&lt;span style="color:#0000ff;"&gt;prototype&lt;/span&gt;.equals = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;(atom)
{
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (isNil(atom) || !isAtom(atom))
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;;
		
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;() == atom.&lt;span style="color:#0000ff;"&gt;name&lt;/span&gt;();
}&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Su evaluaci&amp;oacute;n se basa en un environment (un diccionario que asocia nombres con valores, pero que pueden estar anidados: un environment puede ser padre de otro) y en el nombre del &amp;aacute;tomo. N&amp;uacute;meros, strings son objetos Javascript y no necesitan ser implementados como &amp;aacute;tomos. En una implementaci&amp;oacute;n &amp;ldquo;cl&amp;aacute;sica&amp;rdquo; de Lisp todos los elementos son SExpressions (expresiones simb&amp;oacute;lica) capaces de ser evaluadas. Ahora, yo tengo un AjLisp.evaluate que acepta cualquier objeto Javascript y detecta si puede ser evaluado en un environment:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; evaluate(x, environment)
{
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (x === &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt; || x === undefined)
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; x;
		
	&lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (x.evaluate != undefined &amp;amp;&amp;amp; &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(x.evaluate) == &amp;quot;&lt;span style="color:#8b0000;"&gt;function&lt;/span&gt;&amp;quot;)
		&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; x.evaluate(environment);
		
	&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; x;
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Test de Atomos:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;test(&amp;quot;&lt;span style="color:#8b0000;"&gt;Atom&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() {
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; environment = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AjLisp.Environment();
	environment.setValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;one&lt;/span&gt;&amp;quot;, 1);
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; one = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AjLisp.Atom(&amp;quot;&lt;span style="color:#8b0000;"&gt;one&lt;/span&gt;&amp;quot;);
	equal(one.evaluate(environment), 1);
	ok(one.isAtom());
	equal(one.isList(), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
	ok(AjLisp.isAtom(one));
	equal(AjLisp.isList(one), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
	equal(one.asString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;one&lt;/span&gt;&amp;quot;);
	equal(one.equals(one), &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; one2 = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AjLisp.Atom(&amp;quot;&lt;span style="color:#8b0000;"&gt;one&lt;/span&gt;&amp;quot;);
	equal(one.equals(one2), &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
});&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Test probando la conducta de Listas:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;test(&amp;quot;&lt;span style="color:#8b0000;"&gt;List&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt;() {
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; list = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AjLisp.List(1,2);
	equals(list.first(), 1);
	equals(list.rest(), 2);
	equal(list.isAtom(),&lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
	equal(list.isList(),&lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
	equal(AjLisp.isAtom(list), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
	equal(AjLisp.isList(list), &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
	equal(list.asString(), &amp;quot;&lt;span style="color:#8b0000;"&gt;(1.2)&lt;/span&gt;&amp;quot;);
	equal(list.equals(list), &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; list2 = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; AjLisp.List(1,2);
	equal(list.equals(list2), &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
	equal(list2.equals(list), &lt;span style="color:#0000ff;"&gt;true&lt;/span&gt;);
	&lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; list3 = AjLisp.makeList(1,2,3);
	equal(list.equals(list3), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
	equal(list3.equals(list), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;);
	list = AjLisp.makeList(&lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
	ok(list.first() === &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
	ok(list.rest().first() === &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;);
});
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Temas pendientes: implementaci&amp;oacute;n de environment, evaluaci&amp;oacute;n de listas, formas y formas especiales, el parser, lambda, mlambda, flambda&amp;hellip;. Me divieggto como loco! ;-) ;-)&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1797930" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Javascript/default.aspx">Javascript</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_26002300_243_3B00_digo+Abierto/default.aspx">Proyectos de C&amp;#243;digo Abierto</category></item><item><title>Presentando Programación Funcional, AjLisp y Clojure</title><link>http://msmvps.com/blogs/lopez/archive/2010/11/05/presentando-programaci-243-n-funcional-ajlisp-y-clojure.aspx</link><pubDate>Fri, 05 Nov 2010 15:10:26 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1781688</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1781688</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/11/05/presentando-programaci-243-n-funcional-ajlisp-y-clojure.aspx#comments</comments><description>&lt;p&gt;Ayer, Jueves 4 de Noviembre, tuve el placer de compartir una charla con &lt;a href="http://twitter.com/MartinSalias"&gt;@MartinSalias&lt;/a&gt; y &lt;a href="http://twitter.com/rodolfof"&gt;@RodolfoF&lt;/a&gt;, sobre Programación Funcional. La dimos como una charla del nuevo emprendimiento de Martin:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.codeandbeyond.org/" href="http://www.codeandbeyond.org/"&gt;http://www.codeandbeyond.org/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/codeandbeyond.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;El lugar fue las instalaciones de &lt;a href="http://twitter.com/southworks"&gt;@Southworks&lt;/a&gt;, donde tuvimos proyector, sillas, sonido, y catering (incluyendo cervezas!! ;-). El evento quedó grabado, así que esperamos que Martín lo publique.&lt;/p&gt;  &lt;p&gt;Un resumen de lo que dieron Martín y Rodolfo: Martín presentó Programación Funcional en general, comentando sobre Cálculo Lambda, Lisp y la historia de los lenguajes de programación funcional, como ML, Caml, F# y otros. Luego me tocó mi turno, más abajo doy detalles. Tercer parte, de nuevo Martín mostrando F#, y finalmente, Rodolfo mostrando que C# desde el principio es funcional, y dando ejemplos de código procedural vs funcional.&lt;/p&gt;  &lt;p&gt;No desesperen, entonces, que todo quedará disponible para verlo en línea. &lt;/p&gt;  &lt;p&gt;Mientras, en este post, quería dejar enlaces y comentarios breves de mi intervención en la charla.&lt;/p&gt;  &lt;p&gt;Primero, la primera parte presentación se basó en una que ya había dado para &lt;a href="http://twitter.com/southworks"&gt;@southworks&lt;/a&gt;: &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Presentations/LambdaPresentation.pptx"&gt;LambdaPresentation.pptx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;La presentación de ayer en &lt;a href="http://cid-9f903f3d6db0c176.office.live.com/self.aspx/Presentations/LambdaPresentation.pptx"&gt;LispClojure.pptx&lt;/a&gt; (no es gran cosa, más que algunos enlaces, tiene varios slides en blanco, ver las notas, donde hay código de ejemplo).&lt;/p&gt;  &lt;p&gt;Mostré código de cálculo lambda de mi proyecto AjLambda:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2009/02/25/presenting-ajlambda-lambda-calculus-implementation-in-c/"&gt;Presenting AjLambda: Lambda Calculus Implementation in C#&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2009/02/26/presentando-ajlambda-implementaci-243-n-de-c-225-lculo-lambda-en-c.aspx"&gt;Presentando AjLambda: implementación de Cálculo Lambda en C#&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Si quieren conocer sobre cálculo lambda, desde las matemáticas y lógica, dejé historia y enlaces que usé en &lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.zoomblog.com/archivo/2009/04/14/notas-sobre-el-Calculo-Lambda.html"&gt;Notas sobre Cálculo Lambda&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Trabajé unos minutos mostrando Lambdas en AjLisp. &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx"&gt;Posts sobre el proyecto AjLisp&lt;/a&gt;. Ahí van a encontrar otras implementaciones, como AjScheme, y un AjSharpure, (Work in Progress).&lt;/p&gt;  &lt;p&gt;La parte de Clojure la basé en la más larga, detallada y excelente charla de &lt;a href="http://twitter.com/unclebob"&gt;@unclebob&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://vimeo.com/15046335"&gt;Uncle Bob Martin&amp;#39;s &amp;quot;Clojure - Up Close and Personal&amp;quot;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Usé el ejemplo de multithreading en Clojure con transacciones en memoria:&lt;/p&gt;  &lt;p&gt;&lt;a title="https://github.com/sfraser/MultithreadedGameOfLife" href="https://github.com/sfraser/MultithreadedGameOfLife"&gt;https://github.com/sfraser/MultithreadedGameOfLife&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hace ya unos años, escribí sobre &lt;a href="http://msmvps.com/blogs/lopez/archive/2008/10/11/recursos-de-f-y-programaci-243-n-funcional.aspx"&gt;Recursos de F# y Programación Funcional&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/F_2300_/default.aspx"&gt;Mis posts sobre F#&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx"&gt;Mis posts sobre Programación Funcional&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Mis enlaces:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/functionalprogramming"&gt;http://delicious.com/ajlopez/functionalprogramming&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/lisp"&gt;http://delicious.com/ajlopez/lisp&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/f#"&gt;http://delicious.com/ajlopez/f#&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/clojure"&gt;http://delicious.com/ajlopez/clojure&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/monads"&gt;http://delicious.com/ajlopez/monads&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/lambda"&gt;http://delicious.com/ajlopez/lambda&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/scheme"&gt;http://delicious.com/ajlopez/scheme&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para los que les interesa Lisp, les recomiendo el libro y más:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://mitpress.mit.edu/sicp/full-text/book/book.html"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/"&gt;Video Lectures by Hal Abelson and Gerald Jay Sussman&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://sicpinclojure.com/"&gt;Structure and Interpretation of Computer Programs adapted for the Clojure programming language&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/sicp"&gt;http://delicious.com/ajlopez/sicp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Algo más matemático, que mencioné al pasar:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/categorytheory"&gt;http://delicious.com/ajlopez/categorytheory&lt;/a&gt;    &lt;br /&gt;&lt;a title="http://www.delicious.com/ajlopez/grothendieck" href="http://www.delicious.com/ajlopez/grothendieck"&gt;http://www.delicious.com/ajlopez/grothendieck&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Alexander_Grothendieck"&gt;Alexander Grothendieck&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://www.google.com/url?sa=t&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CBcQFjAA&amp;amp;url=http%3A%2F%2Fen.wikipedia.org%2Fwiki%2FNicolas_Bourbaki&amp;amp;rct=j&amp;amp;q=Bourbaki&amp;amp;ei=eBXUTMPUC4H98Abc5PTcCw&amp;amp;usg=AFQjCNGli_Amtj7sZfRJOzYfxk0GeURw6g&amp;amp;cad=rja"&gt;Nicolas Bourbaki&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1781688" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/F_2300_/default.aspx">F#</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/F+Sharp/default.aspx">F Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx">Programaci&amp;#243;n Funcional</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Clojure/default.aspx">Clojure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category></item><item><title>CodeCamp en Buenos Aires: Intérpretes y Compiladores en .NET</title><link>http://msmvps.com/blogs/lopez/archive/2010/08/31/codecamp-en-buenos-aires-int-233-rpretes-y-compiladores-en-net.aspx</link><pubDate>Tue, 31 Aug 2010 09:21:16 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1776938</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1776938</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/08/31/codecamp-en-buenos-aires-int-233-rpretes-y-compiladores-en-net.aspx#comments</comments><description>&lt;p&gt;El próximo sábado tendremos CodeCamp en Buenos Aires:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.codecamp.com.ar" href="http://www.codecamp.com.ar"&gt;http://www.codecamp.com.ar&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/codecamp.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Les recomiendo una visita al blog (en la página principal) y a la agenda:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.codecamp.com.ar/agenda.aspx" href="http://www.codecamp.com.ar/agenda.aspx"&gt;http://www.codecamp.com.ar/agenda.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;donde hay actividades y charlas desde la mañana hasta la tarde, sobre Azure, Entity Framework 4, .NET 4, Arquitectura de Software (por &lt;a href="http://twitter.com/MartinSalias" target="_blank"&gt;@MartinSalias&lt;/a&gt;), WPF, IronRuby, DynamicDataCenter, SQL Server, Silverlight, ASP.NET MVC, HyperV, WCF, SQL Azure, HTML5, Windows 7, y demos de las Células (vean por ejemplo el video de &lt;a href="http://www.codecamp.com.ar/sinerg%c3%ada-una-c%c3%a9lula-microsoft-con-todas-las-letras.aspx" target="_blank"&gt;Sinergia en una Célula Microsoft&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;Gracias a &lt;a href="http://twitter.com/masaez" target="_blank"&gt;@masaez&lt;/a&gt;, que me invitó al evento, en el Track 4 (16:35), Sala Arquitectura, daré una charla sobre Intérpretes y Compiladores en .NET. Los que me leen por aquí, saben que es uno de mis temas preferidos: construir lenguajes con distintos paradigmas de programación, y para usarlos en proyectos (como AjBasic en &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjGenesis/default.aspx" target="_blank"&gt;AjGenesis&lt;/a&gt;). La charla es de 75 minutos, con preguntas y respuestas.&lt;/p&gt;  &lt;p&gt;Mi idea es visitar temas como:&lt;/p&gt;  &lt;p&gt;- Cómo construir un Intérprete, con pasos en detalle, usando TDD.   &lt;br /&gt;- Tokens, Lexer, Parser, Expresiones, Comandos    &lt;br /&gt;- Ejemplos de intérpretes, de distintos tipos de lenguajes, como &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx" target="_blank"&gt;AjSharp&lt;/a&gt;, &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjTalk/default.aspx" target="_blank"&gt;AjTalk&lt;/a&gt; (bytecodes a la Smalltalk), &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx" target="_blank"&gt;AjLisp&lt;/a&gt; (más funcional), o &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjIo/default.aspx" target="_blank"&gt;AjIo&lt;/a&gt;, tendré que elegir algunos.    &lt;br /&gt;- Comentar los lenguajes que han sido portados a .NET    &lt;br /&gt;- Descubrir IL (Intermediate Language) y generar código desde nuestros programas    &lt;br /&gt;- Ejemplo de AST (Abstract Syntax Tree)    &lt;br /&gt;- La aparición de los lambda. Compilación de Expressions    &lt;br /&gt;- Compilación dinámica de expressions    &lt;br /&gt;- Dynamic Runtime Library, ejemplos de lenguajes implementados    &lt;br /&gt;- Y espero transmitir algo de ¿por qué más lenguajes?&lt;/p&gt;  &lt;p&gt;Como siempre, el código, enlace, presentación que prepare, quedaran aquí publicados en próximo post.&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1776938" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjBasic/default.aspx">AjBasic</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx">Programaci&amp;#243;n Funcional</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx">AjSharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/TDD/default.aspx">TDD</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjTalk/default.aspx">AjTalk</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Dynamic+Language+Runtime/default.aspx">Dynamic Language Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjIo/default.aspx">AjIo</category></item><item><title>AjCoreLisp y MinimaLisp, un intérprete Lisp mínimo</title><link>http://msmvps.com/blogs/lopez/archive/2010/05/04/ajcorelisp_2D00_and_2D00_minimalisp_2D00_a_2D00_minimal_2D00_lisp_2D00_interpreter_2D00_implementation.aspx</link><pubDate>Tue, 04 May 2010 09:47:46 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1764833</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1764833</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/05/04/ajcorelisp_2D00_and_2D00_minimalisp_2D00_a_2D00_minimal_2D00_lisp_2D00_interpreter_2D00_implementation.aspx#comments</comments><description>&lt;p&gt;Como mencioné en:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2010/01/04/ajlisp-family-implementing-lisp-interpreters-in-c/" target="_blank"&gt;AjLisp family: Implementing Lisp Interpreters in C#&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;estuve trabajando en dos intérpretes Lisp: &lt;strong&gt;AjLisp&lt;/strong&gt; y &lt;strong&gt;AjSharpure&lt;/strong&gt; (un intérprete tipo Clojure). Pero quería explorar cuál es el núcleo del lenguaje, la mímima parte que debería ser implementada, para tener un intérprete Lisp.&lt;/p&gt;  &lt;p&gt;Entonces, escribí &lt;strong&gt;AjCoreLisp&lt;/strong&gt;. Pueden bajarlo del proyecto Google Code&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp" href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp"&gt;http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Está implementado en C#. La solución:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajcorelisp01.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;tiene 5 proyectos:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;AjCoreLisp&lt;/strong&gt;: la librería de clases, núcleo del proyecto, implementando el lenguaje base, pero sin parser ni lexer, sólo en runtime de ejecución.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;AjCoreLisp.Tests&lt;/strong&gt;: como es costumbre, desarrollé la librería anterior usando Test-Driven Development. Este es el proyecto de tests de la librería.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;MinimaLisp&lt;/strong&gt;: Una prueba de concepto. Tiene lexer, parser, y una mínima máquina que define el ambiente inicial. Muestra el uso de la librería núcleo, construyendo un intérprete Lisp mínimo.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;MiminaLisp.Console&lt;/strong&gt;: el intérprete de consola interactivo.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;MiminaLisp.Test&lt;/strong&gt;: Tests TDD escritos para el desarrollo de MinimaLisp.&lt;/p&gt;  &lt;p&gt;La interfaz raíz &lt;strong&gt;IExpression&lt;/strong&gt;:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IExpression
    {
        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Evaluate(IEnvironment environment);
    }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Todo Lisp tiene soporte de lista. Esta es la &lt;strong&gt;IList&lt;/strong&gt; interfaz:&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IList : IExpression
    {
        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; First { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; }
        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Rest { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; }
        IList Next { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; }
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;No actualización de los campos de la lista, es inmutable. Si queremos agregar que pueda cambiarse, hay que derivar de este proyecto, y poner la nueva implementación en un nuevo proyecto (como podría ser MinimaLisp u otro). Notar que tomado de Clojure la idea de tener Rest and Next: la primera retorna un objeto. Uso la segunda cuando espero que el resto de la lista sea una lista también.&lt;/p&gt;

&lt;p&gt;Todo form (cabeza ejecutable de lista) implementa &lt;strong&gt;IForm&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IForm
    {
        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Apply(IEnvironment environment, IList arguments);
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Entonces, la clase &lt;strong&gt;Form&lt;/strong&gt; implementa &lt;strong&gt;IForm&lt;/strong&gt; y &lt;strong&gt;IExpression&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Form : IForm, IExpression
    {
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IList parameters;
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IIdentifier parameter;
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IList body;
        &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; IEnvironment environment;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Form(IList parameters, IList body, IEnvironment environment)
        {
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.parameters = parameters;
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.body = body;
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.environment = environment;
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Form(IIdentifier parameter, IList body, IEnvironment environment)
        {
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.parameter = parameter;
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.body = body;
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.environment = environment;
        }
&lt;span style="color:#008000;"&gt;// ....&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Evaluate(IEnvironment environment)
        {
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;;
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;virtual&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Apply(IEnvironment environment, IList arguments)
        {
            IEnvironment newenv;
            
            &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.parameter != &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;)
                newenv = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.MakeNewEnvironmentList(arguments);
            &lt;span style="color:#0000ff;"&gt;else&lt;/span&gt;
                newenv = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.MakeNewEnvironment(arguments);
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; Machine.EvaluateBody(&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.body, newenv);
        }
&lt;span style="color:#008000;"&gt;// ....&lt;/span&gt;
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Noten que &lt;strong&gt;Form&lt;/strong&gt; no evalúa sus argumentos. Este es el trabajo de la clase derivada &lt;strong&gt;Function&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Function : Form, IExpression
    {
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Function(IList parameters, IList body, IEnvironment environment)
            : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(parameters, body, environment)
        {
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; Function(IIdentifier parameter, IList body, IEnvironment environment)
            : &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;(parameter, body, environment)
        {
        }
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Apply(IEnvironment environment, IList arguments)
        {
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;.Apply(environment, BaseForm.EvaluateList(arguments, environment));
        }
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Como es usual, macros tienen una “vuelta de tuerca”: evalúan su cuerpo, pero entonces, evalúan el valor retornado:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Macro : Form, IExpression
    {
&lt;span style="color:#008000;"&gt;// ...&lt;/span&gt;
        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Apply(IEnvironment environment, IList arguments)
        {
            &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt; = &lt;span style="color:#0000ff;"&gt;base&lt;/span&gt;.Apply(environment, arguments);
            &lt;span style="color:#0000ff;"&gt;value&lt;/span&gt; = Machine.Resolve(&lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;, environment);
            &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; Machine.Evaluate(&lt;span style="color:#0000ff;"&gt;value&lt;/span&gt;, environment);
        }
    }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;(Machine.Resolve está relacionado con una implementación de Delayed Evaluation, que uso para conseguir una especie de Tail Recursion). Ok, bastante código fuente por ahora. Miren el código del proyecto para más detalles. El punto principal es que &lt;strong&gt;AjCoreLisp&lt;/strong&gt; implementa pocas primitivas:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajcorelisp02.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;El enlace de primitivas al ambiente actual es el trabajo del MinimaLisp &lt;strong&gt;Machine:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;        &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; MinimalMachine()
        {
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;first&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; First());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;rest&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Rest());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;cons&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Cons());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;quote&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Quote());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;define&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Define());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;lambda&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Lambda());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;flambda&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; FormLambda());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;mlambda&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; MacroLambda());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;let&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Let());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;letrec&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; RecursiveLet());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;eval&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Evaluate());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;if&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; If());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;do&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Do());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;nil?&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; IsNil());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;list?&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; IsList());
            &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.Environment.SetValue(&amp;quot;&lt;span style="color:#8b0000;"&gt;equal?&lt;/span&gt;&amp;quot;, &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; IsEqual());
        }
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Basado ese conjunto de primitivas, pude escribir más funciones:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;(define list x x)
(define definem 
  (mlambda x 
    (list 
      &amp;#39;define 
      (first x)
      (cons &amp;#39;mlambda (rest x))
    )
  )
)
(define mapfirst (fn lst)
  (if (nil? lst)
    nil
    (cons 
      (fn (first lst)) 
      (mapfirst fn (rest lst))
    )
  )
)
    
(define mapcond (fn lst)
  (if (nil? lst)
    nil
    (if (fn (first lst))
      (cons 
        (first lst) 
        (mapcond fn (rest lst))
      )
      (mapcond fn (rest lst))
    )
  )
)
(define append (x y) (if (nil? x) y (cons (first x) (append (rest x) y))))
  
(definem cond lst
  (if (nil? lst)
    nil 
    (list 
      &amp;#39;if 
      (first (first lst)) 
      (cons &amp;#39;do (rest (first lst))) 
      (cons &amp;#39;cond (rest lst))
    )
  )
)
(define atom? (x)
  (cond 
    ((nil? x) t)
    ((list? x) nil)
    (t t)
  )
)
(definem and lst
  (if (nil? lst)
    t
    (list 
      &amp;#39;if 
      (first lst)
      (cons &amp;#39;and (rest lst))
      nil
    )
  )
)
(definem or lst
  (if (nil? lst)
    nil
    (list 
      &amp;#39;if 
      (first lst)
      t
      (cons &amp;#39;or (rest lst))
    )
  )
)
(define not (x)
  (if x
    nil
    t
  )
)
(definem backquote (lst) 
  (cond 
      ((nil? lst) nil)
        ((atom? lst) (list &amp;#39;quote lst))
        ((equal? (first lst) &amp;#39;unquote) (first (rest lst)))
        ((and (list? (first lst)) (equal? (first (first lst)) &amp;#39;unquote-slice)) (list &amp;#39;append (first (rest (first lst))) (list &amp;#39;backquote (rest lst))))
        (t (list &amp;#39;cons (list &amp;#39;backquote (first lst)) (list &amp;#39;backquote (rest lst))))
  )
)
(definem while lst
  (list &amp;#39;if (list &amp;#39;not (first lst)) nil (cons &amp;#39;do (rest lst)) (cons &amp;#39;while lst))
)&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Me gusta mi implementación de &lt;strong&gt;backquote&lt;/strong&gt; (para usar en expansión de macros), un mini “tour-de-force” de este lenguaje. Estos tests dan verde (notar el uso de unquote y unquote-slice):&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;this.EvaluateAndCompare(&amp;quot;(backquote (a b c))&amp;quot;, &amp;quot;(a b c)&amp;quot;);
this.EvaluateAndCompare(&amp;quot;(backquote (a (b c) d))&amp;quot;, &amp;quot;(a (b c) d)&amp;quot;);
this.Evaluate(&amp;quot;(define x &amp;#39;(b b))&amp;quot;);
this.EvaluateAndCompare(&amp;quot;(backquote (a (unquote x) c))&amp;quot;, &amp;quot;(a (b b) c)&amp;quot;);
this.EvaluateAndCompare(&amp;quot;(backquote (a ((unquote x)) c))&amp;quot;, &amp;quot;(a ((b b)) c)&amp;quot;);
this.EvaluateAndCompare(&amp;quot;(backquote (a (unquote-slice x) c))&amp;quot;, &amp;quot;(a b b c)&amp;quot;);
this.EvaluateAndCompare(&amp;quot;(backquote (a ((unquote-slice x)) c))&amp;quot;, &amp;quot;(a (b b) c)&amp;quot;);
this.EvaluateAndCompare(&amp;quot;(backquote (a (unquote-slice x) (unquote-slice x) c))&amp;quot;, &amp;quot;(a b b b b c)&amp;quot;);
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;No hay soporte de números. Escribí algunos tests usando implementaciones tipo Peano:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;(define succ (x)
  (cons x nil))
  
(define pred (x)
  (first x))
(define add (x y)
  (if (nil? x)
    y
    (add (pred x) (succ y))
  )
)
&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Hace un rato que no toco y mejoro el código, pero mi próximo paso podría ser refactorizar AjLisp (intérprete más completo) para basarse o tomar ideas de este intérprete núcleo. Ahora, tengo una idea más clara de lo que es necesario, esencial, y de lo que es accesorio en un intérprete Lisp.&lt;/p&gt;

&lt;p&gt;Y me divertí escribiendo esto &amp;quot;:-)&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1764833" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_26002300_243_3B00_n+Funcional/default.aspx">Programaci&amp;#243;n Funcional</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjCoreLisp/default.aspx">AjCoreLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Proyectos+de+C_F300_digo+Abierto/default.aspx">Proyectos de Código Abierto</category></item><item><title>Refactoreando AjLisp: un intérprete Lisp escrito en C#</title><link>http://msmvps.com/blogs/lopez/archive/2010/01/10/refactoring_2D00_ajlisp_2D00_a_2D00_lisp_2D00_interpreter_2D00_written_2D00_in_2D00_c.aspx</link><pubDate>Sun, 10 Jan 2010 11:50:51 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1750792</guid><dc:creator>lopez</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1750792</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/01/10/refactoring_2D00_ajlisp_2D00_a_2D00_lisp_2D00_interpreter_2D00_written_2D00_in_2D00_c.aspx#comments</comments><description>&lt;p&gt;En estos días estuve reimplementando el núcleo de mi intérprete Lisp de código abierto &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx" target="_blank"&gt;AjLisp&lt;/a&gt;. Había escrito sobre la anterior versión en el 2008:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2008/07/30/ajlisp-a-lisp-interpreter-in-net/"&gt;AjLisp: a Lisp interpreter in .NET&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/07/31/ajlisp-un-int-233-rprete-lisp-en-net.aspx" target="_blank"&gt;AjLisp: un intérprete Lisp en .NET&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Es trabajo en progreso. Pueden bajar el código de:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjLisp"&gt;http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjLisp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(hay otras dos implementaciones en ese repositorio, en desarrollo: &lt;a href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjScheme" target="_blank"&gt;AjScheme&lt;/a&gt;, un Lisp tipo Scheme, y &lt;a href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjSharpure" target="_blank"&gt;AjSharpure&lt;/a&gt;, que intenta seguir las ideas de &lt;a href="http://clojure.org" target="_blank"&gt;Clojure&lt;/a&gt;). Debería escribir sobre esas implementaciones. Este post es el inicial en una serie sobre AjLisp. Es una corta introducción al estado actual del proyecto.&lt;/p&gt;  &lt;p&gt;El principal cambio en esta nueva versión: el intérprete puede manejar objetos y valores nativos. La alternativa hubiera sido apuntar a esos objetos a través de “wrappers”, alguna clase que implemente SymbolicExpression o similar. Pero elegí manejar directamente objetos nativos. Para eso, cambié las primitivas y clases relacionadas para que recibieran como argumentos objetos en vez de IExpression. Sigue habiendo una interfaz IExpression, defined como:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IExpression
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;    {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Evaluate(ValueEnvironment environment);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;    }
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;El ValueEnvironment (planeo cambiarle el nombre a BindingEnvironment, y derivarlo de alguna interfaz tipo IBindingEnvironment) mantiene una asociación anidada de nombres y valores:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisp03.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Hay un interfaz IFunction:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;interface&lt;/span&gt; IFunction
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;    {
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;        &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; Apply(List arguments, ValueEnvironment environment);
&lt;/pre&gt;&lt;pre style="font-size:12px;margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;background-color:#ffffff;"&gt;    }&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;que debería ser implementada por cualquier form expression (la cabeza de una lista a evaluar).&lt;/p&gt;

&lt;p&gt;Las dos clases principales que representan los tipos núcleo del AjLisp son identificadores y listas:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisp04.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Todo el proyecto fue armado siguiendo Test-Driven Development, así que no tuve problemas en cambiar la versión anterior: tenía toda una batería de tests que me ayudó en el proceso de refactoring. Este es el estado actual de los test:&lt;/p&gt;

&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/ajlisp05.png" alt="" /&gt; &lt;/p&gt;

&lt;p&gt;Debería escribir sobre:&lt;/p&gt;

&lt;p&gt;- La implementación de ValueEnvironment
  &lt;br /&gt;- Manejo de objetos nativos 

  &lt;br /&gt;- El tipo List y su evaluación 

  &lt;br /&gt;- Evaluación de Identifier 

  &lt;br /&gt;- Las primitivas implementadas 

  &lt;br /&gt;- El Lexer y el Parser 

  &lt;br /&gt;- Operaciones numéricas 

  &lt;br /&gt;- Números racionales (AjLisp puede manejar pares enteros numerador/denominador)&lt;/p&gt;

&lt;p&gt;Ahora, luego de lo que aprendí desarrollando estos proyectos (AjLisp, AjScheme, AjSharpure), estoy escribiendo un núcleo mínimo &lt;a href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp" target="_blank"&gt;AjCoreLisp&lt;/a&gt;, para mostrar cuáles son las primitivas mínimas para crear un intérprete Lisp. Armado con esa implementación, me gustaría explorar alternativas de compilación, en vez de ser sólo intérprete. Mi primer candidato es Dynamic Language Runtime. Otro podría ser la producción de código C# directo. Sería demasiado encarar esa exploración sobre un intérprete “más grande”. Primero, entonces, estudiaré sobre compilar un intérprete con menos primitivas, más condensado.&lt;/p&gt;

&lt;p&gt;Nos leemos!&lt;/p&gt;

&lt;p&gt;Angel “Java” Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 

  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1750792" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C_26002300_243_3B00_digo+Abierto/default.aspx">C&amp;#243;digo Abierto</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Programaci_F300_n/default.aspx">Programación</category></item><item><title>La familia AjLisp: implementado intérpretes Lisp en C#</title><link>http://msmvps.com/blogs/lopez/archive/2010/01/05/ajlisp_2D00_family_2D00_implementing_2D00_lisp_2D00_interpreters_2D00_in_2D00_c.aspx</link><pubDate>Tue, 05 Jan 2010 10:15:27 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1749745</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1749745</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2010/01/05/ajlisp_2D00_family_2D00_implementing_2D00_lisp_2D00_interpreters_2D00_in_2D00_c.aspx#comments</comments><description>&lt;p&gt;En los últimos meses, estuve activo escribiendo intérpretes Lisp. Desde los ochenta, me gusta escribir ese tipo de intérpretes. Uno de mis ejercicios preferidos cuando estudio un nuevo lenguaje de programación, es escribir un intérprete Lisp en ese lenguaje (otro ejercicio es escribir un intérprete del lenguaje en estudio).&lt;/p&gt;  &lt;p&gt;En el 2008, publiqué un código escrito en C#, &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/AjLisp/default.aspx" target="_blank"&gt;AjLisp&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://ajlopez.wordpress.com/2008/07/30/ajlisp-a-lisp-interpreter-in-net/" target="_blank"&gt;AjLisp: a Lisp interpreter in .NET&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2008/07/31/ajlisp-un-int-233-rprete-lisp-en-net.aspx" target="_blank"&gt;AjLisp: un intérprete Lisp en .NET&lt;/a&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;A la mitad del 2009, comencé a investigar &lt;a href="http://clojure.org" target="_blank"&gt;Clojure&lt;/a&gt;. Dedicí explorar las nuevas ideas de ese lenguaje, reinplementánlo en C# (el Clojure original está escrito en Java, pero hay una versión en .NET, que compila usando DLR, Dynamic Language Runtime). Clojure compila a bytecodes Java. Mi versión es sólo un intérprete (debería estudiar y aprender sobre DLR o compilación .NET, y sobre cómo pasar el árbol de mi intérprete a código compilado). El resultado de todo esto es “work in progress”, se llama AjSharpure (se llamaba AjClojure, pero tuve que cambiar el nombre). Pueden ver el código, en desarrollo, en:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjSharpure" href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjSharpure"&gt;http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjSharpure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Inicialmente, mi idea era portar “uno a uno” el código de Java del Clojure original, pero me dí cuenta al tiempo que su código base no es fácilmente leíble, no tiene test en código, ninguna especificación acerca de la conducta esperada de docenas de clases y centeneares de métodos. Así que paré el desarrollo, y repensé el camino a seguir. Tomé coraje, olvidé el código inicial, y comencé de nuevo, de abajo hacia arriba, usando a fondo Test-Driven Development (TDD), implementando pieza por pieza, para ir consiguiendo parte por parte la conducta esperada externa del lenguaje, en vez de seguir de cerca su implementación interna.&lt;/p&gt;  &lt;p&gt;Ahora está algo tranquilo el desarrollo de AjSharpure, porque estoy estudiando formas de implementar lo que me falta, como variables, Shared Transactional Memory, y otros temas, como References. Mientras, volví a mi versión 2008 de &lt;a href="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/AjLisp/default.aspx" target="_blank"&gt;AjLisp&lt;/a&gt;. Escribí una nueva versión en 2009, haciendo un refactoring importante, armado de lo que había aprendido con AjSharpure. Ahora, tiene acceso y manejo de objetos y valores nativos. El trunk está en:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjLisp" href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjLisp"&gt;http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjLisp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;No hay un Lisp “base”, y hay DOS principales dialectos: Common Lisp y Scheme. No me gustan algunas cosas de Common Lisp (debería escribir un post sobre mi razones), así, que para conocer más sobre Clojure y otros Lisp actuales, comencé a escribir AjScheme, un intérprete que implementa mucho de lo que es la referencia de Scheme (renuncié a implementar definición de macros como en el Scheme original, uso mis más conocidas mlambdas y expansión de macros):&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjScheme" href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjScheme"&gt;http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjScheme&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;El AjLisp nació siguiendo un viejo libro de &lt;a href="http://pagesperso-systeme.lip6.fr/Christian.Queinnec/WWW/Queinnec.html" target="_blank"&gt;Christian Queinnec&lt;/a&gt; (un libro de los ochenta, no uno de sus más nuevos). No pude encontrar el código del libro en la web. Queinnec incluía en el texto el código de un intérprete Lisp escrito en su propio Lisp. No tengo el libro acá (lo tengo en mi segundo cubil). Me puse a investigar sobre lo mínimo que necesita ser implementado en un Lisp básico. Así que estos días estoy trabajando en el AjCoreLisp:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp" href="http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp"&gt;http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;No tiene parser ni lexer. La idea es implementar un intérprete mínimo usando AjCoreLisp como la base: el resultado es MinimaLisp, y está incluido en ese trunk. Estoy implementando las mínimas primitvas, y estoy tratando de escribir el resto de las forms más comunes como funciones o macros. Una decisión “geek” ;-) : implementar la expasión de macros con backspace escribiéndola como una macro! El resultado en:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://pastie.org/765371" href="http://pastie.org/765371"&gt;http://pastie.org/765371&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Una vez que tenga AjCoreLisp/MinimaLisp estabilizado, haré refactor de AjLisp, AjScheme, para usar el kernel más pulido, pero agregaré como primitivas las forms más usadas. Debería medir el impacto de implementar forms más usadas como macros, en lugar de primitivas. Tengo confianza en poder hacer todos esos cambios, porque todo lo escrito está vigilado por una batería de tests (el haber seguido TDD y tener tests me ha salvado el día muchas veces, cuando he refactorizado mucho del código base).&lt;/p&gt;  &lt;p&gt;Como próxima misión: escribir posts sobre estos diferentes intérpretes, variaciones sobre un leit-motiv: las hermosas ideas del lenguaje Lisp.&lt;/p&gt;  &lt;p&gt;Para los que quieran estudiar más sobre Lisp, mis enlaces sobre el tema:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/lisp"&gt;http://delicious.com/ajlopez/lisp&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/scheme"&gt;http://delicious.com/ajlopez/scheme&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/clojure"&gt;http://delicious.com/ajlopez/clojure&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/commonlisp"&gt;http://delicious.com/ajlopez/commonlisp&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez    &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1749745" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjSharpure/default.aspx">AjSharpure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjCoreLisp/default.aspx">AjCoreLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjScheme/default.aspx">AjScheme</category></item><item><title>Lord of the REPLs (Read Eval Print Loops) y CodePad</title><link>http://msmvps.com/blogs/lopez/archive/2009/09/16/lord_2D00_of_2D00_the_2D00_repls_2D00_read_2D00_eval_2D00_print_2D00_loops_2D00_and_2D00_codepad.aspx</link><pubDate>Wed, 16 Sep 2009 09:34:07 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1723758</guid><dc:creator>lopez</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1723758</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/09/16/lord_2D00_of_2D00_the_2D00_repls_2D00_read_2D00_eval_2D00_print_2D00_loops_2D00_and_2D00_codepad.aspx#comments</comments><description>&lt;p&gt;En estos días, estuve trabajando escribiendo lenguajes interpretados. Mi primer interés es &lt;a href="http://clojure.org/" target="_blank"&gt;Clojure&lt;/a&gt;, estoy trabajando en una implementación de las ideas de Clojure en C#, escribiendo desde 0, pueden ver lo que estoy haciendo en:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjSharpure" href="http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjSharpure"&gt;http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjSharpure&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;El año pasado escribí un intérprete Lisp &lt;a title="AjLisp- a Lisp interpreter in .NET" href="http://ajlopez.wordpress.com/2008/07/30/ajlisp-a-lisp-interpreter-in-net/"&gt;AjLisp- a Lisp interpreter in .NET&lt;/a&gt;, &lt;a href="http://msmvps.com/blogs/lopez/archive/2008/07/31/ajlisp-un-int-233-rprete-lisp-en-net.aspx" target="_blank"&gt;AjLisp – un intérprete Lisp en .NET&lt;/a&gt;, que quiero mejorar, pero en las últimas semanas me dediqué más a escribir un intérprete tipo Scheme:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjScheme" href="http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjScheme"&gt;http://code.google.com/p/ajlisp/source/browse#svn/trunk/AjScheme&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Con tanta actividad con lenguajes “lispy”, investigué sobre otras implementaciones. Mis descubrimientos fueron agregados, como es usual, a mi delicious:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://delicious.com/ajlopez/lisp"&gt;http://delicious.com/ajlopez/lisp&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/clojure"&gt;http://delicious.com/ajlopez/clojure&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://delicious.com/ajlopez/scheme"&gt;http://delicious.com/ajlopez/scheme&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Una de las joyitas que encontré, es esta Google App Engine:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://code.google.com/p/lotrepls/" href="http://code.google.com/p/lotrepls/"&gt;http://code.google.com/p/lotrepls/&lt;/a&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;LotREPLs is a multi-lingual read-eval-print-loop in your browser powered by Google App Engine and the Java runtime. It&amp;#39;s a technical demo, not something to do serious work with. The following languages are supported: &lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;BeanShell &lt;/li&gt;      &lt;li&gt;Clojure &lt;/li&gt;      &lt;li&gt;JavaScript &lt;/li&gt;      &lt;li&gt;Python &lt;/li&gt;      &lt;li&gt;Ruby &lt;/li&gt;      &lt;li&gt;Scala &lt;/li&gt;      &lt;li&gt;Scheme &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;Pueden probara en línea en:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://lotrepls.appspot.com/" href="http://lotrepls.appspot.com/"&gt;http://lotrepls.appspot.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/repl03.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Podemos ingresar un comando, y ver el resultado de la evaluación, sin instalar nada en la máquina local.&lt;/p&gt;  &lt;p&gt;Otra aplicación similar, que soporta C, C++, D, Haskell, Lua, Ocaml, PHP, Perl, Python, Ruby, Scheme, Tcl, es:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://codepad.org/" href="http://codepad.org/"&gt;http://codepad.org/&lt;/a&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;codepad.org is an online compiler/interpreter, and a simple collaboration tool.      &lt;br /&gt;Paste your code below, and codepad will run it and give you a short URL you can use to share it in chat or email. &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/repl01.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Podemos ingresa el código, y se puede referenciarse por URL, para compartir con otros desarrolladores:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/repl02.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;Si seguimos así, un día, todas nuestras herramientas estarán en el browser… :-)&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez    &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1723758" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Clojure/default.aspx">Clojure</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lisp/default.aspx">Lisp</category></item><item><title>Popularidad de Lenguajes de Programación</title><link>http://msmvps.com/blogs/lopez/archive/2009/07/08/popularidad-de-lenguajes-de-programaci-243-n.aspx</link><pubDate>Wed, 08 Jul 2009 09:50:06 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1698705</guid><dc:creator>lopez</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1698705</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2009/07/08/popularidad-de-lenguajes-de-programaci-243-n.aspx#comments</comments><description>&lt;p&gt;Me temo que &lt;a href="http://en.wordpress.com/tag/ajlisp/" target="_blank"&gt;AjLisp&lt;/a&gt; y &lt;a href="http://en.wordpress.com/tag/ajbasic" target="_blank"&gt;AjBasic&lt;/a&gt; lo usamos yo y nadie más… snif… :-). Pero hay lenguajes más populares que esos. Ya es clásica la lista de TIOBE Software:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html" href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"&gt;http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/langpop01.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;donde aparece Java como el lenguaje más popular, lo que no me asombra. Pero sí me llama la atención la popularidad de C y C++, que deben tener su gran uso en el ambiente Unix, Linux, y otros. Como cuarto, encuentro hoy, Julio de 2009, a PHP, que lo entiendo: la mayor parte del código de sitios dinámicos está en PHP, lejos quedaron los años del predominio del venerable Perl. Y recién en sexto y séptimo lugar, está Visual Basic (parece que agrupan el de .NET y el clásico), y C#. Vean que al final de la lista, aparecen lenguajes con mínimos porcentajes, pero aparecen: RPG, Pascal, Abap, Lisp/Scheme. Más abajo, en la misma página encontraran la lista de posición 21 a 50, donde aparecen COBOL, Objective-C, Fortran, Logo, Prolog, Ada (todavía anda por ahí? :-), Scala, Erlang…. y esta es la lista de 51 a 100:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;ABC, AD, Algol, Alpha, Applescript, Beta, Boo, C shell, cg, Clean, Cobra, cT, Curl, Dylan, Eiffel, Euphoria, Factor, Fan, Icon, IDL, Inform, Io, Lingo, MAD, Magic, Maple, Mathematica, MAX/MSP, MOO, MUMPS, Natural, Oberon, Occam, Oz, PL/I, Postscript, PowerBuilder, Progress, Q, R, Revolution, REXX, S-lang, SIGNAL, SPSS, SuperCollider, VBScript, Verilog, VHDL, XSLT&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Notable lista, recomendaría tantos lenguajes de esa lista, simplemente para aprender nuevas formas de programar (notable que aparezca todavía MUMPS, REXX, tendría que ver con más detalle a Io). Esta lista de popularidad se basa en el examen de búsquedas en Google, hace un tiempo pasaron a agregar MSN y Yahoo.&lt;/p&gt;  &lt;p&gt;Pero en estos días, encontré otra página:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://langpop.com/" href="http://langpop.com/"&gt;http://langpop.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.todocontenidos.com/images/articles/langpop02.png" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;con información de ranking de popularidad, pero con agrupadas con distintas fuentes, como Yahoo Search, search en Google Code, Freshmeat, Craiglist, Amazon.&lt;/p&gt;  &lt;p&gt;En lo que veo hoy ahí, julio de 2009, según Yahoo Search C es más popular que Java. Pero para Craiglist, primero PHP, segundo SQL (!!!), en Amazon ganan C, C++ y C#, por encima de Java. Y así, noto dispersión de los resultados, dependiendo de la fuente.&lt;/p&gt;  &lt;p&gt;La popularidad de un lenguaje importa. No tanto para entender el lenguaje (muchos lenguajes “boutique” tienen interesantes conceptos, a estudiar con detalle), sino para tener una idea de qué tecnología ha sido adoptada por la comunidad, pero habría que ver más allá: por qué la eligieron, y en qué tipo de proyectos. Dudo que haya muchas aplicaciones desktop, en PHP.&lt;/p&gt;  &lt;p&gt;Resumen: gran cantidad de lenguajes, hay lenguajes viejos, desde COBOL y Smalltalk, y más “nuevos” como Boo, Ruby, Python. Y `cuatros grandes grupos: Java, C/C++, lenguajes .NET (VB.NET, C#), PHP, como claros grupos líderes.&lt;/p&gt;  &lt;p&gt;Pienso que, como desarrolladores de software, debemos tener contacto con esos cuatro grupos, y además, con alguno de los “otros”, para aprender otras ideas y formas de programar.&lt;/p&gt;  &lt;p&gt;No&amp;#160; me enojo si intentan ver &lt;a href="http://en.wordpress.com/tag/ajlisp" target="_blank"&gt;AjLisp&lt;/a&gt; o &lt;a href="http://en.wordpress.com/tag/ajbasic" target="_blank"&gt;AjBasic&lt;/a&gt;… :-)&lt;/p&gt;  &lt;p&gt;Nos leemos!&lt;/p&gt;  &lt;p&gt;Angel “Java” Lopez   &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;    &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1698705" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Java/default.aspx">Java</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/PHP/default.aspx">PHP</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Smalltalk/default.aspx">Smalltalk</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Desarrollo+de+Software/default.aspx">Desarrollo de Software</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjBasic/default.aspx">AjBasic</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category></item><item><title>AjLisp: un intérprete Lisp en .NET</title><link>http://msmvps.com/blogs/lopez/archive/2008/07/31/ajlisp-un-int-233-rprete-lisp-en-net.aspx</link><pubDate>Thu, 31 Jul 2008 13:30:41 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1642818</guid><dc:creator>lopez</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1642818</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/07/31/ajlisp-un-int-233-rprete-lisp-en-net.aspx#comments</comments><description>&lt;p&gt;Soy un entusiasta de escribir intérpretes, especialmente del tipo Lisp. Mi primer intérprete Lisp fue escrito al principio de los 80, usando el lenguaje assembler de un Intel 808x. Era un trabajo muy &amp;quot;geek&amp;quot;. Una de las características más &amp;quot;tricky&amp;quot; de implementar es un recolector de basura (garbage collector). Por suerte, desde mediados de los 90 tenemos Java y su&amp;nbsp; librería de clases como una tecnología ampliamente disponible con un garbage collector decente. En este siglo, .NET es la nueva plataforma de lenguajes con GC..&lt;/p&gt; &lt;p&gt;En el&amp;nbsp;2005, &lt;a href="http://blog.salias.com.ar/" target="_blank"&gt;Martin Salias&lt;/a&gt;&amp;nbsp;y yo dimos un TechNight,&amp;nbsp;aquí en Buenos Aires, Argentina, para la oficina local de Microsoft. Trató sobre lenguajes implementados en .NET.&amp;nbsp;Fue&amp;nbsp;la primera vez que presenté F#, así como&amp;nbsp;P# y otros.&amp;nbsp;Despues de esa charla, la misma noche viajé a Mar del Plata, para dar otra charla sobre ASP.NET. Mar del&amp;nbsp;Plata es una bella ciudad, en frente del océano Atlántico,&amp;nbsp;a la que trato de volver cada año. Entonces, era mi primer visita luego de treinta años. En el viaje,&amp;nbsp;&amp;quot;nació&amp;quot; AjLisp.&lt;/p&gt; &lt;p&gt;Esa versión era un intérprete Lisp escrito en Visual Basic .NET. El pasado domingo, lo porté a C# (usando alguna opción de menú de SharpDevelop, ¿alguna otra herramienta que conozcan?). El código original fue usado hace unas semanas en mi post sobre&amp;nbsp;VPL:&lt;/p&gt; &lt;p&gt;&lt;a title="Lisp-like interpreter using DSS and VPL" href="http://ajlopez.wordpress.com/2008/06/09/lisp-like-interpreter-using-dss-and-vpl/"&gt;Lisp-like interpreter using DSS and VPL&lt;/a&gt;&lt;br /&gt;&lt;a title="Int&amp;eacute;rprete tipo Lisp usando DSS y VPL" href="http://msmvps.com/blogs/lopez/archive/2008/06/11/int-233-rprete-tipo-lisp-usando-dss-y-vpl.aspx"&gt;Intérprete tipo Lisp usando DSS y VPL&lt;/a&gt;&lt;/p&gt; &lt;p&gt;La nueva versión C# version está publicada en Google Code en:&lt;/p&gt; &lt;p&gt;&lt;a title="http://code.google.com/p/ajlisp/" href="http://code.google.com/p/ajlisp/"&gt;http://code.google.com/p/ajlisp/&lt;/a&gt;&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajlispgoogle.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;Me gusta&amp;nbsp;Google Code: tiene soporte de SVN, asi que uso mi cliente local TortoiseSVN para enviar los cambios en el proyecto.&lt;/p&gt; &lt;h3&gt;La solución&lt;/h3&gt; &lt;p&gt;Tiene tres proyectos:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajlispsln.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;AjLisp&lt;/strong&gt;: el proyecto núcleo, una librería, que puede ser invocada desde otra aplicación.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AjLisp.Tests&lt;/strong&gt;: Todos los tests, usando NUnit 2.2.8. Si no tienen NUnit, pueden remover el proyecto de la solución.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;AjLisp.Console&lt;/strong&gt;: un simple programa de consola.&lt;/p&gt; &lt;h3&gt;Los tipos&lt;/h3&gt; &lt;p&gt;Una interfaz base es &lt;strong&gt;IAtom&lt;/strong&gt;:&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:1fdf33bc-cbd8-428f-a086-0a973fd0b495" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;interface&lt;/span&gt;&lt;span style="color:#000000;"&gt; IAtom
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; IsAtom();
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Otra es &lt;strong&gt;IList&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:af4e475d-5592-440e-8e6e-cb47ae443def" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;interface&lt;/span&gt;&lt;span style="color:#000000;"&gt; IList
    {
        SymbolicExpression First
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        }

        SymbolicExpression Rest
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;get&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;;
        }

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;bool&lt;/span&gt;&lt;span style="color:#000000;"&gt; IsList();
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Todos los tipos derivan de una SymbolicExpression:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:8b612956-e1db-4f06-8e0b-1641a003b53f" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#0000FF;"&gt;namespace&lt;/span&gt;&lt;span style="color:#000000;"&gt; AjLisp.Types
{
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression : IList, IAtom
    {
 ....
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Implementé los tipos comunes a usar en un&amp;nbsp;Lisp, como List, Atom, Identifier, Function (para invocar a primitivas y funciones generadas por lambdas), True, Nil...:&lt;/p&gt;
&lt;p&gt;Existe una clase Environment para mantener valores asociados a nombres. Cada Environment tiene un Environment padre, para mantener una lista de ambientes con valores.&lt;/p&gt;
&lt;p&gt;La clase Interpreter es la principal a manejar: tiene un Environment y define algunos nombres para las primitivas iniciales:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:3f5d7f67-0306-4998-a6cc-d503bea9ba10" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Interpreter
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;private&lt;/span&gt;&lt;span style="color:#000000;"&gt; Environment environment &lt;/span&gt;&lt;span style="color:#000000;"&gt;=&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; Environment();

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; Interpreter()
        {
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;nil&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, Nil.Value);
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;t&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, True.Value);
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;cons&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrCons());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;first&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrFirst());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;car&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrFirst());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;rest&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrRest());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;cdr&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrRest());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;list&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrList());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;quote&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrQuote());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;append&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrAppend());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;cond&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrCond());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;atom&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrAtom());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;eval&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrEval());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;null&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrNull());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;lambda&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrLambda());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;progn&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrProgN());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;flambda&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrFLambda());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;nlambda&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrNLambda());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;mlambda&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrMLambda());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;numberp&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrNumberP());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;functionp&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrFunctionP());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;idp&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrIdP());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;define&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrDefine());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;definef&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrDefineF());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;definen&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrDefineN());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;definem&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrDefineM());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;eq&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrEq());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;if&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrIf());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;let&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrLet());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;lets&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrLetS());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;set&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrSet());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;consp&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrConsP());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;less&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrLess());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;greater&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrGreater());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;plus&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrPlus());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;difference&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrDifference());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;times&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrTimes());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;quotient&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrQuotient());
            Define(&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;remainder&lt;/span&gt;&lt;span style="color:#000000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color:#000000;"&gt;, &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrRemainder());
        }

....&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Uds. pueden escribir sus propias primitivas y agregarlas a este constructor.&lt;/p&gt;
&lt;h3&gt;Las primitivas&lt;/h3&gt;
&lt;p&gt;El intérprete tiene las primitivas usuales:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajlispprim.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Hay primitivas, que antes de su invocación, evalúan los argumentos recibidos. Son las que derivan de &lt;strong&gt;Subr&lt;/strong&gt;:&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:837dc062-a1ab-414c-8512-5dcd05e044df" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;width:551px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; Subr : Function
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Execute(SymbolicExpression args, Environment env);

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Apply(SymbolicExpression form, Environment env)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Execute(form.Rest.Evaluate(env), env);
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;form.First es la función, y&amp;nbsp;form.Rest es la lista de argumentos. Para evaluar el form, Function usa un objeto Environment. &lt;/p&gt;
&lt;p&gt;Otras primitivas no evalúan sus argumentos, derivan de &lt;strong&gt;FSubr&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:e90ae27a-5861-4b80-8123-f7afef71c8f1" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;width:526px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubr : Function
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;abstract&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Execute(SymbolicExpression args, Environment env);

        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Apply(SymbolicExpression form, Environment env)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; Execute(form.Rest, env);
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Una de las primitivas más interesantes, es la implementación de lambda, llamada FSubrLambda:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:71b9c875-831e-4eb0-aea8-5035f7fe4cf9" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;width:599px;padding-top:0px;"&gt;&lt;pre style="background-color:White;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; FSubrLambda : FSubr
    {
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;override&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Execute(SymbolicExpression args, Environment env)
        {
            &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;return&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;new&lt;/span&gt;&lt;span style="color:#000000;"&gt; SubrClosure(args.First, env, args.Rest);
        }
    }
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Crea un Closure, una manera de recordar el Environment actual para usarlo en una futura invocación de la expresión lambda. Implementé también NLambda, FLambda, MLambda: N es por NonSpread (maneja su lista de argumentos como si fuera un solo argumento), F es cuando no son evaluados los argumentos antes de la invocación, y M es por Macro (tengo que revisar hasta donde implementé esta &amp;quot;feature&amp;quot;).&lt;/p&gt;
&lt;h3&gt;Los tests&lt;/h3&gt;
&lt;p&gt;Toda la funcionaliad está cubierta por tests. Configuré el proyecto AjLisp.Test para ejecuter NUnit GUI:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajlisptests.png" alt="" /&gt; &lt;/p&gt;
&lt;h3&gt;La consola&lt;/h3&gt;
&lt;p&gt;AjLisp.Console es un simple programa de consola. Pueden ingresar una expresión y la evalúa:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/ajlispconsole.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Es tan simple, que hay que usar Control-C para salir... ;-).&lt;/p&gt;
&lt;h3&gt;Próximos pasos&lt;/h3&gt;
&lt;p&gt;Hay tanto para hacer. Quiero mejorar algunos puntos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reescribir interfaces y clases de base 
&lt;li&gt;Manejar e invocar objetos .NET nativos 
&lt;li&gt;Tratar a Reales y Enteros por separado (hoy a ambos, al operar, los trata como valores double) 
&lt;li&gt;Revisar Macro expansion
&lt;li&gt;Mejor consola 
&lt;li&gt;Librería de ejemplos 
&lt;li&gt;Un manual mínimo&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;La idea es llegar a extender este mini lenguaje para ser usado como la base programación de agentes distribuidos. Sería bueno portarlo a Java. Entonces, la conducta de los agentes y su estado puede ser escrito en este lenguaje, y viajar a distintos nodos de la grilla, de forma independiente a la plataforma.&lt;/p&gt;
&lt;p&gt;Bueno, son sueños. Ahora, el estado actual: está funcionando, y me divertí escribiéndolo. Disfruten!&lt;/p&gt;
&lt;p&gt;(Este artículo es una traducción a Spanish, desde el Anglish (Angel&amp;#39;s English) original:&lt;br /&gt;&lt;a title="AjLisp- a Lisp interpreter in .NET" href="http://ajlopez.wordpress.com/2008/07/30/ajlisp-a-lisp-interpreter-in-net/"&gt;AjLisp- a Lisp interpreter in .NET&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;)&lt;/p&gt;
&lt;p&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com/en"&gt;http://www.ajlopez.com/en&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1642818" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Inteligencia+Artificial/default.aspx">Inteligencia Artificial</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/C+Sharp/default.aspx">C Sharp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Lenguajes+de+Programaci_26002300_243_3B00_n/default.aspx">Lenguajes de Programaci&amp;#243;n</category></item><item><title>Intérprete tipo Lisp usando DSS y VPL</title><link>http://msmvps.com/blogs/lopez/archive/2008/06/11/int-233-rprete-tipo-lisp-usando-dss-y-vpl.aspx</link><pubDate>Wed, 11 Jun 2008 14:22:24 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1634011</guid><dc:creator>lopez</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/lopez/rsscomments.aspx?PostID=1634011</wfw:commentRss><comments>http://msmvps.com/blogs/lopez/archive/2008/06/11/int-233-rprete-tipo-lisp-usando-dss-y-vpl.aspx#comments</comments><description>&lt;p&gt;Este fin de semana estuve programando algunas primitivas de un intérprete Lisp usando DSS Service Compoenntes. El núcleo del intérprete fue derivado de mi trabajo previo con AjLisp, un intérprete que todavía no publiqué. Escribí el ejemplo usando Visual Studio 2008 con el CTP v2.0 de &lt;a href="http://www.microsoft.com/robotics" target="_blank"&gt;Microsoft Robotics Developer Studio&lt;/a&gt;. El ejemplo está publicado en mi Skydrive como &lt;a href="http://cid-9f903f3d6db0c176.skydrive.live.com/self.aspx/Examples/DSS/DssLisp.zip" target="_blank"&gt;DssLisp.zip&lt;/a&gt;.&lt;/p&gt; &lt;h3&gt;La solución&lt;/h3&gt; &lt;p&gt;Consiste de dos proyectos: una librería de clases llamada&amp;nbsp;AjLisp (una versión revisada de mi intérprete original en VB.NET):&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispajlisp.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;y un proyecto C# de Dss Service, que tiene varios service components implementados:&lt;/p&gt; &lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispdss.png" alt="" /&gt; &lt;/p&gt; &lt;p&gt;No tiene manifiesto inicial. El proyecto está pensado para ser usado desde diagramas de Visual Programming Language (VPL).&lt;/p&gt; &lt;p&gt;Varios de estos componentes reciben y retornan una SymbolicExpression, el tipo base de mi intérprete. Veamos por ejemplo, los mensajes del componente Rest, que dada una lista devuelve la misma lista sin el primer elemento:&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="57F11A72-B0E5-49c7-9094-E3A15BD5B5E7:1618d506-618e-4139-9950-8639333a6fc3" style="padding-right:0px;display:inline;padding-left:0px;float:none;padding-bottom:0px;margin:0px;padding-top:0px;"&gt;&lt;pre style="background-color:White;"&gt;&lt;div&gt;&lt;span style="color:#000000;"&gt;    [DataContract()]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; ExecuteRequest
    {
        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Expression;
    }

    [DataContract]
    &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;class&lt;/span&gt;&lt;span style="color:#000000;"&gt; ExecuteResponse
    {
        [DataMember]
        &lt;/span&gt;&lt;span style="color:#0000FF;"&gt;public&lt;/span&gt;&lt;span style="color:#000000;"&gt; SymbolicExpression Result;
    }
    
&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Para compilar estos componentes, deben ajustar las referencias y directorios del proyecto DSS (ahora apuntan a mis directorios locales y a mi instalación local de Microsoft Robotics Developer Studio).&lt;/p&gt;
&lt;h3&gt;Usando VPL&lt;/h3&gt;
&lt;p&gt;Hay tres programas VPL incluidso en los ejemplos. Usan los componentes compilados de la solución. Tuve un problema con estos programas VPL. No pude ejecutarlos desde la opción de&amp;nbsp; &lt;strong&gt;Run&lt;/strong&gt;. Hay que usar &lt;strong&gt;Build -&amp;gt; Compile as a Service&lt;/strong&gt;, y ahora, lanzarlos con &lt;strong&gt;Run -&amp;gt; Run Compiled Services&lt;/strong&gt;. Creo que el origen del problema es que al armar el diagrama estoy mapeando mensajes propios, no solamente tipos primitivos o Strings. Para recompilar los diagramas, tienen que ajustar las propiedades en cada proyecto VPL:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl0.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;El primero,&amp;nbsp; &lt;strong&gt;DssLispVpl1,&amp;nbsp;&lt;/strong&gt;calcula (first &amp;#39;(a b c)):&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl1.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="center"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p align="left"&gt;Hay dos componentes LispParser y LispToString, que ayudan a convertir de string a SymbolicExpression y viceversa.&lt;/p&gt;
&lt;p align="left"&gt;El segundo diagrama es &lt;strong&gt;DssLispVpl2&lt;/strong&gt;:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl2.png" alt="" /&gt; &lt;/p&gt;
&lt;p align="left"&gt;Usa el componente LispAppend para concatenar dos listas predefinidas como Data.&lt;/p&gt;
&lt;p align="left"&gt;El tercero es un min intérprete &lt;strong&gt;DsspLispInterpreter&lt;/strong&gt;:&lt;/p&gt;
&lt;p align="center"&gt;&lt;img src="http://www.ajlopez.com/images/articles/dsslispvpl3.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Tengo que mejorar el tratamiento de errores. Ahora, si ocurre una excepción, no devuelve un Fault, y encontes se genera una causality, que hace que el programa se interrumpa.&lt;/p&gt;
&lt;p&gt;Podría implementar contratos genéricos, y reusarlos en los componentes, por ejemplo, un contrato GenericBinaryOperation.&lt;/p&gt;
&lt;h3&gt;Problemas&lt;/h3&gt;
&lt;p align="left"&gt;Fallé completamente cuando quise escribir una Activity, para implementar una función Reverse de una lista. La actividad se llamaba a sí misma recursivamente, pero en el código generador retornaba desde la última invocación recursiva, sin pasar por las intermedias. El problema es causado porque en todo ese proceso se utiliza la misma instancia de actividad, y al retornar por una puerta el resultado, TODOS los procesos pendientes de esa actividad están escuchando por esa puerta (eso es lo que veo que pasa). Otra piedra en el camino es que las actividades solo aceptan valores primitivos o string como datos en el mensaje de entrada. Puedo solucionar el problema, generando el código de la actividad, levantando la solución, y cambiando los parámetros que trata de, digamos, string a SymbolicExpression.&lt;/p&gt;
&lt;p align="left"&gt;Un componente interesante, es el componente Uncons, que retorna DOS expresiones simbólicas en su mensaje de respuesta: dada una lista, retorna su cabeza y su cola. Esos dos miembros de la respuesta pueden ser procesados luego en paralelo en dos ramas del diagrama.&lt;/p&gt;
&lt;h3&gt;Conclusiones&lt;/h3&gt;
&lt;p align="left"&gt;Como en otros posts y ejemplos, encontré la orquestación de componentes DSS via VPL como algo poderoso e interesante, pero le faltan algunas cosas, como el soporte de un objeto genérico o tipos&amp;nbsp;nuestros. Creo que se puede implementar varias primitivas de lenguajes funcionales y usar a VPL para programar sobre ellas. VPL tendría problemas con la recursividad (o no encontré una forma aceptable de hacerla funcionar). Este ejercicio,&amp;nbsp;podría expandirse a otras ideas:&lt;/p&gt;
&lt;p align="left"&gt;- Manejar una pipeline/tubería para procesar un mensaje genérico (puedo usar un object como DataMember en un mensaje, siempre y cuando no lo envía a otro Host de DSS)&lt;br /&gt;- Tener balanceo de carga&lt;br /&gt;- Serializar/deserializar objetos entre hosts&lt;br /&gt;- Implementar algún workflow o patrones de integración de aplicaciones usando VPL&lt;/p&gt;
&lt;p align="left"&gt;Nos leemos!&lt;/p&gt;
&lt;p align="left"&gt;Angel &amp;quot;Java&amp;quot; Lopez&lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;&lt;/p&gt;
&lt;p align="left"&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1634011" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/lopez/archive/tags/.NET/default.aspx">.NET</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Concurrency+and+Coordination+Runtime/default.aspx">Concurrency and Coordination Runtime</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/Decentralized+Software+Services/default.aspx">Decentralized Software Services</category><category domain="http://msmvps.com/blogs/lopez/archive/tags/AjLisp/default.aspx">AjLisp</category></item></channel></rss>