Archive for the '8871' Category

DylanSharp Implementando Dylan en C# (1) El Proyecto

Saturday, June 28th, 2014

Hace unos meses comencé a implementar un intérprete del lenguaje Dylan, para practicar TDD en C#, además de aprender algo de programación funcional. Leo en:

http://opendylan.org/

Dylan is a multi-paradigm functional and object-oriented programming language. It is dynamic while providing a programming model designed to support efficient machine code generation, including fine-grained control over dynamic and static behaviors.

Lo interesante de Dylan es que incorpora tipos y objetos. Por ahora no pretendo generar código de máquina, sino, siguiendo “baby steps”, implementar los conceptos principales del lenguaje como un intérprete. Me gustaría igual agregar acceso a las librerías .NET, lo que me parece interesante para ampliar el alcance del lenguaje. Pueden aprender más del lenguaje en:

http://opendylan.org/documentation/intro-dylan/index.html

El proyecto que escribo en C# está en:

https://github.com/ajlopez/DylanSharp

y su estructura actual es:

Consta de una librería de clases, y un proyecto de tests. Hasta ahora hay algunas expresiones simples implementadas, un Parser, un Lexer, y un concepto del lenguaje implementado como clase C#: List, que implementa listas como en Lisp. Como en otros proyectos, tengo Context para mantener los valores de las variables, y recuperarlas por nombre. Notablemente, en Dylan las variables tienen tipo, pero aún no estoy controlando los tipos, simplemente evaluando expresiones cualesquiera. Tendré que tomar la decisión en algún momento, de controlar los tipos en el momento de compilar/procesar el programa. Según:

http://opendylan.org/documentation/intro-dylan/expressions-variables.html#type-declarations

Type mismatch errors should be caught at compile time.

Pero ya llegará el momento. Avanzando con TDD, tengo confianza en que llegado el caso podré hacer un refactor/rediseño de los que llamo quirúrgico, sin que sufra mucho el proyecto. Podría hacerlo en la próxima iteración o más adelante. Antecendentes de ese “approach” los he tenido en ScalaSharp, por ejemplo.

Próximos pasos: seguir implementado expresiones, definiciones de clases, módulos, comandos, funciones anónimas. Y controlar los tipos.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Presentando Clojure

Thursday, April 19th, 2012

Actualización: se podrá ver en línea en el momento (6:30PM Buenos Aires) desde http://mulesoft.adobeconnect.com/jugar/

Como comenté en otro post, hoy voy a dar una charla introductoria sobre Clojure, en el Java User Group de Argentina, en Buenos Aires. En este post quiero poner los principales recursos que he consultado.

La lista de Clojure en español: http://groups.google.com/group/clojure-hispano

Los ejemplos de dos libros:

https://github.com/joyofclojure/book-source
http://pragprog.com/titles/shcloj/source_code

Mis simples ejemplos:

https://github.com/ajlopez/ProgrammingLanguagesSamples/tree/master/Clojure

Y el de @paraseba https://github.com/paraseba/tictactoe

Las páginas que he visitado:

http://clojure.org
https://github.com/joyofclojure/
http://joyofclojure.com/cljr

http://www.niclas-meier.de/2012/04/first-hundred-days-of-clojure/

http://www.infoq.com/presentations/One-Parenthesis-to-Rule-them-All
http://www.infoq.com/presentations/Event-Driven-Programming-in-Clojure

http://daly.axiom-developer.org/clojure.pdf

https://github.com/sfraser/MultithreadedGameOfLife

http://programming-puzzler.blogspot.com.es/2010/08/racket-vs-clojure.html
https://github.com/paraseba/tictactoe
http://www.infoq.com/interviews/hickey-clojure-reader#

 

Leiningen

https://github.com/technomancy/leiningen

http://leiningen.org

Noir http://webnoir.org/

ClojureScript:

https://github.com/ibdknox/live-cljs

http://www.chris-granger.com/2012/04/12/light-table—a-new-ide-concept/

http://clojure.org/cheatsheet

Los libros:

The Joy of Clojure
http://joyofclojure.com/

Programming Clojure
http://pragprog.com/book/shcloj/programming-clojure

Mis enlaces:

http://delicious.com/clojure+tutorial
http://delicious.com/clojure+video
http://delicious.com/clojure

Si la charla queda publicada en video, agregaré el enlace.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Clojure en el Java User Group de Argentina

Monday, April 16th, 2012

Gracias a el Java User Group de Argentina:

http://www.jugargentina.org/

el próximo jueves participaré de su Meetup en Buenos Aires:

http://www.jugargentina.org/events/60301992/

Se votaron charlas, y la que había sugerido, ganó la encuesta. Voy a presentar una introducción a Clojure, el lenguaje creado por Rick Hickey que ejecuta sobre la VM de Java, tiene también variantes para .NET CLR y hasta hay Clojurescript sobre Javascript.

Mi idea es presentar las características principales del lenguaje, basado en Lisp, pero con ideas nuevas, como:

– Nuevas estructuras (conjuntos, mapas, secuencias …)

– Manejo de concurrencia (por ejemplo, aparece una implementación de Software Transactional Memory)

– Acceso a la librería de Java

Pensé que tenía 20 o 30 minutos disponibles, como en otras meetups. Pero en las reuniones de Jugar se da una sola charla por vez. Así que voy a aprovechar para dar algo más de Clojure, posiblemente use Leiningen y levante Noir (un framework web).

Creo que ya se llenó el cupo, pero si les interesa Java y su actividad, les recomiendo anotarse como miembros del grupo. Como siempre, terminaré publicando por acá los recursos, ejemplos que haya comentado en la charla. Posiblemente, la gente de Jugar la grabe y la comparta por su web. También, el sábado estaré dando una VAN de Alt.NET Hispano, donde uno de los temas será Clojure (además de Ruby y Python).

Mis enlaces del tema:

http://delicious.com/ajlopez/clojure

Mis posts

http://ajlopez.wordpress.com/category/clojure/

Les recuerdo que hay una lista en español sobre Clojure http://groups.google.com/group/clojure-hispano

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Erlang en Buenos Aires (1) Erlounge Marzo 2012

Monday, March 19th, 2012

La semana pasada, el jueves 15 de Marzo, tuve el gusto de asistir a la (primera, creo) reunión del grupo Erlang Argentina, en las oficinas de Inaka Networks en Buenos Aires. El anfitrión principal fue el fundador de la empresa, el bueno de Chad Depue. Ver:

http://www.erlang-factory.com/conference/SFBay2010/speakers/ChadDePue (integrando Lua con Erlang)

Ahí encuentro Datos de 2010:

Chad DePue

Entrepreneur and creator of ErlangInside.com

Ruby Rescue

 

Chad DePue is a software developer and entrepreneur focusing on Ruby on Rails and Erlang through his consulting company Ruby Rescue. He is a former VP of Engineering at Visto Corporation (now Good Technologies) and started his career at Microsoft in the Developer Tools Division. In 2008 Chad moved his family to Buenos Aires, Argentina to, among other things, learn Spanish, a language which he finds much more difficult than Erlang.
Chad recently built a high-performance mobile payment and microlending platform in Erlang and Ruby on Rails, the combination of which he believes provides the rapid development time of Rails with the scalability, fault-tolerance, and easy-redundancy of the Erlang/OTP platform.

http://www.linkedin.com/in/depue

https://twitter.com/#!/chaddepue

@chaddepue

Developer from Seattle, Living in Buenos Aires, Argentina. I have a new consultancy called Inaka Networks focused on Ruby, iPhone, iPad, and Erlang applications

Buenos Aires, Argentina · http://inakanetworks.com

La empresa que fundó es Inaka, donde tienen desarrollos en Erlang, Ruby on Rails, Objective-C (para la programación cliente). Vean sus trabajos:

http://inakanetworks.com/projects/

donde en muchos usan Erlang para procesar concurrentemente mensajes de esas aplicaciones, con alto nivel de escalabilidad.

El lugar de encuentro fue en sus oficinas, calle Darwin al 1100, cerca de Av. Córdoba y J.B.Justo. Es un interesante edificio, que ocupa gran parte de la cuadra, y hasta tiene calles interiores. Antiguamente fue una fábrica de ropa de marca, y luego fue convertida en “loft” repartidos en varios cuerpos. Inaka ocupa uno de esos loft desde Enero de este año, son sus nuevas oficinas. Chad trabajó en Microsoft, Developer Tools, en Seattle, y habla bien español, con ocasionales consultas por algún vocablo. Así que no tuve que apelar a mi Anglish (Angel’s English) para hacerle preguntas. De curioso, conseguí esta información:

– Trabajó en Microsoft Developer Tools, con Visual Basic clásico, y llegó a trabajar también en Visual Basic.NET

– Su trabajo también tocaba Visual Interdev (los noventa… éramos tan pobres 🙂

– Se mudó en 2008, a Argentina. Fue una decisión que tomó, junto con su familia (esposa, ahora 3 hijos), considerando: huso horario, idioma distinto del inglés, seguridad. Pensaban estar tres años, pero al fin se afincó con su nueva empresa acá.

– La empresa comienza a tener forma en 2010

Fui uno de los primeros en llegar a la reunión, donde fuimos recibidos por Chad, Fernando Benavides, Martina Freers (ver http://inakanetworks.com/people/). Sorpresa! Nos tenían preparadas cerveza, “snacks”, papa fritas… gnam! 🙂 Bueno, también había gaseosa, adivinen qué elegí para tomar.. 🙂

Para este Erlounge (esta reunión) estaba previstas dos charlas. Una de Chad, sobre implementar un Redis en Erlang, vean:

https://github.com/inaka/edis (el tema me interesa, estoy implementando algo en C# https://github.com/ajlopez/AjKeyvs lo interesante para mí es cliente/servidor, implementación de las estructuras de datos, y espero llegar a sharding)

y otra de Fernando Benavides

sobre escalar Erlang, basado en el caso del proyecto:

https://github.com/inaka/match_stream

Son dos charlas que van a presentar ahora a fines de Marzo en Erlang Factory 2012. Pueden ver los slides de la charla de Fernando en https://github.com/inaka/erlang_factory

Los asistentes fuimos alrededor de veinte (no conté, a ojo de buen cubero), y fue interesante encontrar a gente en Argentina interesada en Erlang, y aún mejor, trabajando, con gran experiencia.

Le pregunté a Fernando sobre su historia con Erlang. Mi resultado de entrevista informal:

– Estudió en la Universidad de Buenos Aires, Ciencias Exactas (uy, recuerdo qué linda bibliote, que visitaba en los ochentas… #soytanviejo 🙂

– Ahí vió que lo que le gustaba era la programación funcional

– Encontró un mensaje (en lista? en tablero de la facultad?) de una empresa, para trabajar en programación funcional

– En la universidad, vió Haskell, en la empresa se encontró con Erlang, y viene programando desde entonces (no tengo el año de inicio de su trabajo en esa empresa, Novamens)

– La empresa desaparece. Se va de vacaciones a Polonia, y ahí aprovecha y aplica para la certificación en Erlang.

– En septiembre de 2010 aparece un mensaje en la lista de Erlang Argentina, pidiendo programadores (era Chad Depue).

– Desde entonces trabaja en Inaka

Bueno, por hoy bastante. Próximos posts: comentarios de la charla de Fernando, y algunos de la charla de Chad (me tuve que ir a las 21hs, ya saben, lo mío es la sopita de pollo a la noche 🙂 y dormirme temprano).

Mientras, pueden ir leyendo:

http://inakanetworks.com/blog/2011/10/07/scale-test-plan-simple-erlang-application/
http://inakanetworks.com/blog/archives/

y ir viendo el código de GitHub https://github.com/inaka

Veremos cuándo se hace el próximo Erlounge. Quisiera dar una charla tipo “Erlang for dummies (like me!)”.  Mis posts en Anglish sobre Erlang:

http://ajlopez.wordpress.com/category/erlang/

Mi pet project, pichón pichón de intérprete Erlang en C# https://github.com/ajlopez/ajerl (a ver si lo pongo como “commitment” para Abril).

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

AjLisp en Ruby (1) Estructura, Clases y Tests

Saturday, December 3rd, 2011

Estoy aprendiendo y practicando Ruby, y como es costumbre, lo hago escribiendo algo interesante para mí: el intérprete AjLisp (hace unos meses lo implementé en Javascript). 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:

https://github.com/ajlopez/AjLispRb

Inicialmente (pueden ver los logs) escribí todo en un solo archivo (código y tests), siguiendo el simple y claro ejemplo:

http://kanemar.com/2006/03/04/screencast-of-test-driven-development-with-ruby-part-1-a-simple-example/

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:

http://guides.rubygems.org/

Tengo pendiente de leer y estudiar:

http://speakerdeck.com/u/pat/p/cut-polish-a-guide-to-crafting-gems
http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html

Así que mi código aún no es una gema. Pero va teniendo la estructura de una:

El directorio lib contiene un solo archivo ajlisp.rb:

require 'ajlisp/list.rb'
require 'ajlisp/named_atom.rb'
require 'ajlisp/context.rb'
require 'ajlisp/string_source.rb'
require 'ajlisp/token.rb'
require 'ajlisp/lexer.rb'
require 'ajlisp/parser.rb'
require 'ajlisp/primitive.rb'
require 'ajlisp/primitive_first.rb'
require 'ajlisp/primitive_rest.rb'
require 'ajlisp/primitive_cons.rb'
require 'ajlisp/primitive_list.rb'
require 'ajlisp/primitive_closure.rb'
require 'ajlisp/fprimitive.rb'
require 'ajlisp/fprimitive_quote.rb'
require 'ajlisp/fprimitive_lambda.rb'
require 'ajlisp/fprimitive_flambda.rb'
require 'ajlisp/fprimitive_let.rb'
require 'ajlisp/fprimitive_closure.rb'
require 'ajlisp/fprimitive_define.rb'
require 'ajlisp/primitive_add.rb'
module 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 "let", FPrimitiveLet.instance
@context.setValue "define", FPrimitiveDefine.instance
@context.setValue "+", PrimitiveAdd.instance
def self.context
    return @context
end
def self.evaluate(context, item)
    if item.is_a? List or item.is_a? NamedAtom
        return item.evaluate(context)
    end
        
    return item	
end
end

Escribí algunas primitivas (formas normales, y formas especiales: estas últimas no evalúan sus parámetros antes de su aplicación, ejemplos: quote y define). Noten que los archivos adicionales los puse en un subdirectorio ajlisp dentro de lib, ¿por qué? Porque cuando este código sea instalado como una gema, todo el directorio lib estará disponible para require, y si hubiera un archivo ahí, se podría hacer require(‘elarchivo’). Es por eso que los archivos adicionales a ajlisp.rb se colocan en otro lado, evitando colisión de nombres. Se recomienda colocarlos debajo de lib (vean el código de gemas que tienen en su instalación de Ruby, o vean ejemplos en GitHub).

El el directorio test hay un archivo test.rb que incluye a los otros archivos de tests:

require 'ajlisp'
require 'test/unit'
require "test_list.rb"
require "test_named_atom.rb"
require "test_context.rb"
require "test_string_source.rb"
require "test_token.rb"
require "test_lexer.rb"
require "test_parser.rb"
require "test_primitive_first.rb"
require "test_primitive_rest.rb"
require "test_primitive_cons.rb"
require "test_primitive_list.rb"
require "test_primitive_closure.rb"
require "test_primitive_add.rb"
require "test_fprimitive_quote.rb"
require "test_fprimitive_lambda.rb"
require "test_fprimitive_let.rb"
require "test_fprimitive_closure.rb"
require "test_fprimitive_flambda.rb"
require "test_fprimitive_define.rb"
require "test_evaluate"

Pueden ejecutar los tests desde la línea de comando:

ruby –Ilib;test test\test.rb

En Windows, dejé el archivo runtest.cmd conteniendo esta línea. Los parámetros –Ilib;test le indican a Ruby que incluya los directorios lib y test para cuando tenga que resolver un require. De esta forma evito poner directorios explícitos (o usar __FILE__) en los require.

Algo de tests:

require 'ajlisp'
require 'test/unit'
class TestList < Test::Unit::TestCase
#...    
    def test_create_with_first
        list = AjLisp::List.new("foo")
        assert_equal("foo", list.first)
        assert_nil(list.rest)
    end
    
    def test_create_with_first_and_rest
        rest = AjLisp::List.new("bar")
        list = AjLisp::List.new("foo", rest)
        assert_equal("foo", list.first)
        assert_not_nil(list.rest)
        assert_equal("bar", list.rest.first)
        assert_nil(list.rest.rest)
    end
    
    def test_create_from_array
        list = AjLisp::List.make [1, "a", "foo"]
        assert_not_nil list
        assert_equal 1, list.first
        assert_equal "a", list.rest.first
        assert_equal "foo", list.rest.rest.first
        assert_nil list.rest.rest.rest
    end
#..
end

Cada lista en AjLisp es un objeto de esta clase, list.rb:

module AjLisp
class List
    attr_reader :first
    attr_reader :rest
    
    def initialize(first=nil, rest=nil)
        @first = first
        @rest = rest
    end
    
    def evaluate(context)
        form = AjLisp::evaluate(context, @first)
        form.evaluate(context, self)
    end
    
    def self.make(array)
        if array and array.length > 0
            first = array.shift
            
            if first.is_a? Array
                first = make(first)
            elsif first.is_a? Symbol
                first = NamedAtom.new first.to_s
            end
                        
            return List.new first, make(array)
        end 
        
        return nil
    end
end
end

Los méteodos de acceso first y rest 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”.

En mis nuevos tests, ahora incluye el código DENTRO del módulo AjLisp, así me evito de escribir el prefijo AjLisp:: antes de referenciar a una clase:

require 'ajlisp'
require 'test/unit'
module AjLisp
class TestLexer < Test::Unit::TestCase
    def test_get_atom_token
        source = StringSource.new "atom"
        lexer = Lexer.new source
        token = lexer.nextToken
        
        assert_not_nil token
        assert_equal "atom", token.value
        assert_equal TokenType::ATOM, token.type
        assert_nil lexer.nextToken
    end
    def test_get_atom_token_with_spaces
        source = StringSource.new "  atom   "
        lexer = Lexer.new source
        token = lexer.nextToken
        
        assert_not_nil token
        assert_equal "atom", token.value
        assert_equal TokenType::ATOM, token.type
        assert_nil lexer.nextToken
    end
#...
end

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.

Próximos pasos: completar las primitivas (let, letrec, definef, do, if…), macro (mlambda, definem, expansión de macros…)

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

AjLisp en Javascript (Parte 2) Evaluación de Listas, Formas y Formas Especiales

Wednesday, August 31st, 2011

Anterior Post
Siguiente Post

En el anterior post presenté la estructura y creación de átomos y listas. Pero ¿Cómo se evalú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ón de una lista:

List.prototype.evaluate = function(environment) 
{
    var form = this.first().evaluate(environment);		
    return form.apply(this, environment);
}	

El primer elemento debe ser un elemento que evaluado, da un objecto con un .apply como méetodo. Hay dos clases de formas: las normales y las especiales. La implementación de Form:

function Form() {
}
Form.prototype.evaluate = function(environment) { return this; }
Form.prototype.apply = function(list, environment) 
{ 
    if (isNil(list)) return this.eval(list, environment);
    var rest = list.rest();
    if (rest != null)
        rest = rest.evaluateList(environment);
    return this.eval(rest, environment); 
}

La implementación de las especiales:

function SpecialForm() {
}
SpecialForm.prototype.evaluate = function(environment) { return this; }
SpecialForm.prototype.apply = function(list, environment) 
{ 
    if (isNil(list)) return this.eval(list, environment);
    return this.eval(list.rest(), environment);
}

¿Notan la diferencia? Los elementos del resto de la lista SON EVALUADOS en una forma normal. Al contrario, una forma especial no los evalúa. ¿Por qué esa diferencia? Las formas especiales son “primitivas” como (if <cond> <then> <else>…) donde las partes <then> <else>… pueden evaluarse o no bajo el control de la forma especial. Vean:

Special Forms in Lisp

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’s, NLAMBDA’s, and MACRO’s.

¿Ejemplos de Form? Los escribí usando instancias, redefiniendo su método eval:

var listForm = new Form();
listForm.eval = function eval(list) 
{
	return list;
}
var nilpForm = new Form();
nilpForm.eval = function eval(list) 
{
	if (isNil(list))
		return true;
		
	return isNil(list.first());
}
var listpForm = new Form();
listpForm.eval = function eval(list) 
{
	if (isNil(list))
		return true;
		
	return isList(list.first());
}

Un ejemplo de forma especial, el ‘if’:

var ifForm = new SpecialForm();
ifForm.eval = function eval(list, env)
{
	var cond = evaluate(list.first(), env);
	var then = list.rest().first();
	var elsebody = list.rest().rest();
	
	if (!isNil(cond) && cond != false)
		return evaluate(then, env);
	while (!isNil(elsebody)) 
	{
		result = evaluate(elsebody.first(), env);
		elsebody = elsebody.rest();
	}
	
	return result;			
}

Se exponen en el enviroment global:

// Environment
var environment = new Environment();
environment.list = listForm;
environment.first = firstForm;
environment.rest = restForm;
environment.cons = consForm;
environment['do'] = doForm;
environment['if'] = ifForm;
// more settings in environment

Temas para próximos posts: environments, closures, lambdas, macros, el parser y TDD.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Presentando Programación Funcional, AjLisp y Clojure

Friday, November 5th, 2010

Ayer, Jueves 4 de Noviembre, tuve el placer de compartir una charla con @MartinSalias y @RodolfoF, sobre Programación Funcional. La dimos como una charla del nuevo emprendimiento de Martin:

http://www.codeandbeyond.org/

El lugar fue las instalaciones de @Southworks, donde tuvimos proyector, sillas, sonido, y catering (incluyendo cervezas!! ;-). El evento quedó grabado, así que esperamos que Martín lo publique.

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.

No desesperen, entonces, que todo quedará disponible para verlo en línea.

Mientras, en este post, quería dejar enlaces y comentarios breves de mi intervención en la charla.

Primero, la primera parte presentación se basó en una que ya había dado para @southworks: LambdaPresentation.pptx.

La presentación de ayer en LispClojure.pptx (no es gran cosa, más que algunos enlaces, tiene varios slides en blanco, ver las notas, donde hay código de ejemplo).

Mostré código de cálculo lambda de mi proyecto AjLambda:

Presenting AjLambda: Lambda Calculus Implementation in C#
Presentando AjLambda: implementación de Cálculo Lambda en C#

Si quieren conocer sobre cálculo lambda, desde las matemáticas y lógica, dejé historia y enlaces que usé en

Notas sobre Cálculo Lambda

Trabajé unos minutos mostrando Lambdas en AjLisp. Posts sobre el proyecto AjLisp. Ahí van a encontrar otras implementaciones, como AjScheme, y un AjSharpure, (Work in Progress).

La parte de Clojure la basé en la más larga, detallada y excelente charla de @unclebob:

Uncle Bob Martin’s "Clojure – Up Close and Personal"

Usé el ejemplo de multithreading en Clojure con transacciones en memoria:

https://github.com/sfraser/MultithreadedGameOfLife

Hace ya unos años, escribí sobre Recursos de F# y Programación Funcional.

Mis posts sobre F#
Mis posts sobre Programación Funcional

Mis enlaces:

http://delicious.com/ajlopez/functionalprogramming
http://delicious.com/ajlopez/lisp
http://delicious.com/ajlopez/f#
http://delicious.com/ajlopez/clojure
http://delicious.com/ajlopez/monads
http://delicious.com/ajlopez/lambda
http://delicious.com/ajlopez/scheme

Para los que les interesa Lisp, les recomiendo el libro y más:

Structure and Interpretation of Computer Programs
Video Lectures by Hal Abelson and Gerald Jay Sussman
Structure and Interpretation of Computer Programs adapted for the Clojure programming language
http://delicious.com/ajlopez/sicp

Algo más matemático, que mencioné al pasar:

http://delicious.com/ajlopez/categorytheory
http://www.delicious.com/ajlopez/grothendieck
Alexander Grothendieck
Nicolas Bourbaki

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

CodeCamp en Buenos Aires: Intérpretes y Compiladores en .NET

Tuesday, August 31st, 2010

El próximo sábado tendremos CodeCamp en Buenos Aires:

http://www.codecamp.com.ar

Les recomiendo una visita al blog (en la página principal) y a la agenda:

http://www.codecamp.com.ar/agenda.aspx

donde hay actividades y charlas desde la mañana hasta la tarde, sobre Azure, Entity Framework 4, .NET 4, Arquitectura de Software (por @MartinSalias), 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 Sinergia en una Célula Microsoft)

Gracias a @masaez, 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 AjGenesis). La charla es de 75 minutos, con preguntas y respuestas.

Mi idea es visitar temas como:

– Cómo construir un Intérprete, con pasos en detalle, usando TDD.
– Tokens, Lexer, Parser, Expresiones, Comandos
– Ejemplos de intérpretes, de distintos tipos de lenguajes, como AjSharp, AjTalk (bytecodes a la Smalltalk), AjLisp (más funcional), o AjIo, tendré que elegir algunos.
– Comentar los lenguajes que han sido portados a .NET
– Descubrir IL (Intermediate Language) y generar código desde nuestros programas
– Ejemplo de AST (Abstract Syntax Tree)
– La aparición de los lambda. Compilación de Expressions
– Compilación dinámica de expressions
– Dynamic Runtime Library, ejemplos de lenguajes implementados
– Y espero transmitir algo de ¿por qué más lenguajes?

Como siempre, el código, enlace, presentación que prepare, quedaran aquí publicados en próximo post.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

AjCoreLisp y MinimaLisp, un intérprete Lisp mínimo

Tuesday, May 4th, 2010

Como mencioné en:

AjLisp family: Implementing Lisp Interpreters in C#

estuve trabajando en dos intérpretes Lisp: AjLisp y AjSharpure (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.

Entonces, escribí AjCoreLisp. Pueden bajarlo del proyecto Google Code

http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp

Está implementado en C#. La solución:

tiene 5 proyectos:

AjCoreLisp: 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.

AjCoreLisp.Tests: como es costumbre, desarrollé la librería anterior usando Test-Driven Development. Este es el proyecto de tests de la librería.

MinimaLisp: 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.

MiminaLisp.Console: el intérprete de consola interactivo.

MiminaLisp.Test: Tests TDD escritos para el desarrollo de MinimaLisp.

La interfaz raíz IExpression:

    public interface IExpression
    {
        object Evaluate(IEnvironment environment);
    }

Todo Lisp tiene soporte de lista. Esta es la IList interfaz:

 

    public interface IList : IExpression
    {
        object First { get; }
        object Rest { get; }
        IList Next { get; }
    }

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.

Todo form (cabeza ejecutable de lista) implementa IForm:

    public interface IForm
    {
        object Apply(IEnvironment environment, IList arguments);
    }

Entonces, la clase Form implementa IForm y IExpression:

    public class Form : IForm, IExpression
    {
        private IList parameters;
        private IIdentifier parameter;
        private IList body;
        private IEnvironment environment;
        public Form(IList parameters, IList body, IEnvironment environment)
        {
            this.parameters = parameters;
            this.body = body;
            this.environment = environment;
        }
        public Form(IIdentifier parameter, IList body, IEnvironment environment)
        {
            this.parameter = parameter;
            this.body = body;
            this.environment = environment;
        }
// ....
        public object Evaluate(IEnvironment environment)
        {
            return this;
        }
        public virtual object Apply(IEnvironment environment, IList arguments)
        {
            IEnvironment newenv;
            
            if (this.parameter != null)
                newenv = this.MakeNewEnvironmentList(arguments);
            else
                newenv = this.MakeNewEnvironment(arguments);
            return Machine.EvaluateBody(this.body, newenv);
        }
// ....
    }

Noten que Form no evalúa sus argumentos. Este es el trabajo de la clase derivada Function:

    public class Function : Form, IExpression
    {
        public Function(IList parameters, IList body, IEnvironment environment)
            : base(parameters, body, environment)
        {
        }
        public Function(IIdentifier parameter, IList body, IEnvironment environment)
            : base(parameter, body, environment)
        {
        }
        public override object Apply(IEnvironment environment, IList arguments)
        {
            return base.Apply(environment, BaseForm.EvaluateList(arguments, environment));
        }
    }

Como es usual, macros tienen una “vuelta de tuerca”: evalúan su cuerpo, pero entonces, evalúan el valor retornado:

    public class Macro : Form, IExpression
    {
// ...
        public override object Apply(IEnvironment environment, IList arguments)
        {
            object value = base.Apply(environment, arguments);
            value = Machine.Resolve(value, environment);
            return Machine.Evaluate(value, environment);
        }
    }

(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 AjCoreLisp implementa pocas primitivas:

El enlace de primitivas al ambiente actual es el trabajo del MinimaLisp Machine:

        public MinimalMachine()
        {
            this.Environment.SetValue("first", new First());
            this.Environment.SetValue("rest", new Rest());
            this.Environment.SetValue("cons", new Cons());
            this.Environment.SetValue("quote", new Quote());
            this.Environment.SetValue("define", new Define());
            this.Environment.SetValue("lambda", new Lambda());
            this.Environment.SetValue("flambda", new FormLambda());
            this.Environment.SetValue("mlambda", new MacroLambda());
            this.Environment.SetValue("let", new Let());
            this.Environment.SetValue("letrec", new RecursiveLet());
            this.Environment.SetValue("eval", new Evaluate());
            this.Environment.SetValue("if", new If());
            this.Environment.SetValue("do", new Do());
            this.Environment.SetValue("nil?", new IsNil());
            this.Environment.SetValue("list?", new IsList());
            this.Environment.SetValue("equal?", new IsEqual());
        }

Basado ese conjunto de primitivas, pude escribir más funciones:

(define list x x)
(define definem 
  (mlambda x 
    (list 
      'define 
      (first x)
      (cons '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 
      'if 
      (first (first lst)) 
      (cons 'do (rest (first lst))) 
      (cons 'cond (rest lst))
    )
  )
)
(define atom? (x)
  (cond 
    ((nil? x) t)
    ((list? x) nil)
    (t t)
  )
)
(definem and lst
  (if (nil? lst)
    t
    (list 
      'if 
      (first lst)
      (cons 'and (rest lst))
      nil
    )
  )
)
(definem or lst
  (if (nil? lst)
    nil
    (list 
      'if 
      (first lst)
      t
      (cons 'or (rest lst))
    )
  )
)
(define not (x)
  (if x
    nil
    t
  )
)
(definem backquote (lst) 
  (cond 
      ((nil? lst) nil)
        ((atom? lst) (list 'quote lst))
        ((equal? (first lst) 'unquote) (first (rest lst)))
        ((and (list? (first lst)) (equal? (first (first lst)) 'unquote-slice)) (list 'append (first (rest (first lst))) (list 'backquote (rest lst))))
        (t (list 'cons (list 'backquote (first lst)) (list 'backquote (rest lst))))
  )
)
(definem while lst
  (list 'if (list 'not (first lst)) nil (cons 'do (rest lst)) (cons 'while lst))
)

Me gusta mi implementación de backquote (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):

this.EvaluateAndCompare("(backquote (a b c))", "(a b c)");
this.EvaluateAndCompare("(backquote (a (b c) d))", "(a (b c) d)");
this.Evaluate("(define x '(b b))");
this.EvaluateAndCompare("(backquote (a (unquote x) c))", "(a (b b) c)");
this.EvaluateAndCompare("(backquote (a ((unquote x)) c))", "(a ((b b)) c)");
this.EvaluateAndCompare("(backquote (a (unquote-slice x) c))", "(a b b c)");
this.EvaluateAndCompare("(backquote (a ((unquote-slice x)) c))", "(a (b b) c)");
this.EvaluateAndCompare("(backquote (a (unquote-slice x) (unquote-slice x) c))", "(a b b b b c)");

No hay soporte de números. Escribí algunos tests usando implementaciones tipo Peano:

(define succ (x)
  (cons x nil))
  
(define pred (x)
  (first x))
(define add (x y)
  (if (nil? x)
    y
    (add (pred x) (succ y))
  )
)

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.

Y me divertí escribiendo esto ":-)

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

AjIo: Intérprete tipo Io en C#

Saturday, May 1st, 2010

El año pasado, descubrí el lenguaje de programación Io:

http://www.iolanguage.com/

overview

Io is a prototype-based programming language inspired by Smalltalk (all values are objects, all messages are dynamic), Self (prototype-based), NewtonScript (differential inheritance), Act1 (actors and futures for concurrency), LISP (code is a runtime inspectable/modifiable tree) and Lua (small, embeddable).

Tiene una sintaxis simple, sus características están basadas en lenguajes funcionales, Smalltalk, Self y otros. Como de costumbre, quiero escribir mi propia versión, con un cambio: soporte de objetos nativos. Esto es, para implementar un intérprete sobre una máquina virtual con librería de clases. Las actuales opciones son Java y .NET.

Dos semanas atrás, el bueno de @MartinSalias me comentó sobre el lenguaje Io, y apareció de nuevo en mi radar. Entonces, el pasado domingo, comencé mi propia implementación, basado solamente en lo que leí en el sitio. No será el mismo lenguaje, veré que quedará o no adentro de esta implementación. Es trabajo en progreso.

El código está en mi proyecto de Google AjCodeKata:

http://code.google.com/p/ajcodekatas/

En el trunk, en el directorio AjIo. Hay una solución .NET, con tres proyectos:

La librería de clases es el núcleo, el programa de consola puede ser usado para interactuar con el intérprete, y el proyecto de test tiene las pruebas automáticas que escribí durante el proceso de diseño/codificación.

He escrito el lexer, el parser, y los principales objetos del lenguaje usando Test-Driven Development, como acostumbro.

En una de las primeras pruebas del intérprete, podemos escribir:

Hace unos días, implementé los operadores de asignación ::=, :=, = (arreglos de sintaxis adornando los métodos setSlot, newSlot, updateSlot):

Un tiempo més tarde (pueden consultar el History.txt dentro del repositorio), agregué soporte de objectos nativos .NET:

Próximos pasos:

– Escribir más operadores de comparación (sólo escribí ==)
– Números nativos (ahora, sólo son reconocidos por el lexer los enteros, pero pueden manejarse otros tipos, probar 1 / 6, retorna un double)
– Precedencia en operatdores aritméticos (ahora 2 + 2 * 3 retorna 12, en vez 8)
– for, foreach, range, y más (ahora hay sólo if())
– block() (Tengo implementado method())
– include()
– Comenzar a escribir parte de los objetos de la librería original de Io

Sobre este últimos punto: debo decidir cóomo implemento cosas como:

List clone

Posibles opciones:

– List como un objecto derivado de Object (obtenido de(Object clone) con sus propios slots, como wrapper sobre una lista nativa
– List clone retornando objectos ArrayList nativos, teniendo el tipo ArrayList sus slots asociados
– No implementar List, y usar directamente objetos nativos

Como en AjSharp, el Io original tiene agentes y coroutines. Quiero agregar las características de AjSharp (agentes, goroutines, channels, queue channels, futures) en AjIo. Io implementa agentes en “threads” de máquina virtual: esto es, no usa los threads del sistema operativo, sino que la máquina virtual va ejecutando parte de un agente, parte del otro, pasado de un código a otro durante la ejecución  (eso es lo que imagino, no he visto el código de implementación). No tomaré esa aproximación, no por ahora.

Este artículo, en Anglish:

http://ajlopez.wordpress.com/2010/04/30/working-in-ajio-io-like-interpreter-in-c/

Como ven, me he divertido escribiendo todo esto!

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez