• Shortcuts : 'n' next unread feed - 'p' previous unread feed • Styles : 1 2

» Publishers, Monetize your RSS feeds with FeedShow:  More infos  (Show/Hide Ads)


Date: Wednesday, 09 Jul 2014 10:45

Un nuevo mes comenzó, tiempo de revisar mis resoluciones de Junio 2014, y escribir las nuevas:

- Continuar AjErl [pendiente]
- Continuar ScalaSharp [completo] repo 
- Continuar SharpGo [completo] repo
- Alcance de variables en lenguaje Mass [completo] repo
- Comenzar SimpleItems [pendiente]
- Continuar SimpleApps [partial] repo
- Continuar ClojSharp [pendiente]
- Continuar DictSharp [pendiente]
- Primer caso de uso distribuido de AjErl [pendiente]
- Primer caso de uso distribuido de Aktores [pendiente]
- Escribir C# Posts [completo] Posts
- Escribir TDD Post [completo] Post
- Mejorar el código de mi sitio personal [completo]

También estuve trabajando en:

- Crear y publicar primer versión SimpleCurry, para programación funcional en JavaScript [completo]  repo
- Crear y publicar primer versión LoadJsons, lee un modelo JSON desde varios archivos, para JavaScript/Node [completo]  repo
- Crear un sitio dinámicado, definido por JSON, para Express 4 [completo]  repo
- Generar código para Express 4 usando AjGenesisNode [completo]  repo
- Generar código Sinatra usando AjGenesisNode [completo]  repo
- Mejorar AjGenesisNode, AjGenesisNode-Model, AjGenesisNode-Entity [completo]  repo repo repo
- Continuar DylanSharp [completo]  repo
- Crear SharpBus, un service bus tipo Mule, en C# [completo]  repo

Estas son mis resoluciones para Julio 2014:

- Seguir mejorando la generación de código de AjGenesisNode para Express
- Seguir mejorando la generación de código de AjGenesisNode para Sinatra
- Primer generación de código de AjGenesisNode para Laravel 
- Mejorar la carga de módulos y la exportación de variables/funciones en el lenguaje Mass
- Continuar con SharpBus
- Continuar con Dynamic Site
- Dar una charla sobre Node.js/Express
- Dar una jornada sobre Node.js/Express
- Seguir mejorar el código de mi sitio personal
- Escribir post de TDD
- Escribir posts de C#
- Caso de uso distribuido en Aktores
- Revisar, refactorizar y continuar la implementación de RustScript

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Javascript, Proyectos de ..."
Comments Send by mail Print  Save  Delicious 
Date: Monday, 07 Jul 2014 17:18

Gracias a la gente del MUG voy a dar una charla introductoria (gratuita, pero hay que registrarse) ahora en unos días acá en Buenos Aires:

http://www.mug-it.org.ar/Event.aspx?Event=162

Inicio: 23.07.2014 18:30hs, hasta las 20 y monedas | Lugar: Rivadavia 1479 1er Piso

JavaScript no solo tiene cada vez más influencia en el desarrollo cliente/nativo, también ha sabido crecer en el lado del servidor. En esta sesión gratuita veremos la implementación de Node.js, un programa que ejecuta JavaScript. Vacantes limitadas. Inscripción previa obligatoria.

Node.js permite el desarrollo de servidores de distintos protocolos, procesamiento distribuido, y desarrollo web, explotando la entrada/salida asincrónica para mejorar el rendimiento. Bravemente exploraremos como se escribe y ejecuta JavaScript en Node.js, el sistema de módulos, el ecosistema de módulos que tiene, una introducción a desarrollar sitios web con Express, con ejemplos.

Luego, viene una jornada (de un día, con costo, traer notebook para aprovecharla):

http://www.mug-it.org.ar/Event.aspx?Event=163

Lugar: Auditorio del MUG, Rivadavia 1479 Primer Piso "A", Buenos Aires.

Fecha y Horario: Miércoles 30 de julio de 2014 de 9:00 a 17:00 hs. 

 

Contenidos:
1. Introducción a Node.js
1.1. Programación Javascript desde Node sobre el motor V8 
1.2. Entrada/Salida asincrónica 
1.3. Módulos 
1.4. Manejador de paquetes npm
1.5. Elementos de Test-Driven Development 
2. Programación Web con Node.js 
2.1. Módulo HTTP 
2.2. Manejo asincrónico 
2.3. Acceso a MongoDB
3. Programación Web con Express
3.1. Concepto de Middleware 
3.2. Lenguaje de Templates 
3.3. Ejemplos con Páginas y Acceso a Datos
3.4. Programando con JSON
3.5. Elementos de Socket.IO
(*)  Instalar previamente el siguiente software:
Instalador de Node (para Windows y otros) http://nodejs.org/download/
Git bajarlo de http://git-scm.com/
MongoDB bajarlo de http://www.mongodb.org/downloads
La idea de la jornada es practicar Node.js, desde el inicio, y ver de instalar, levantar y examinar ejemplos, de consola y web, para ir viendo cómo es el tema de desarrollo con Node.js, cómo se usan los módulos, el ecosistema que existe, el manejador de paquetes NPM, y Express como framework web. Usaremos MongoDB para la persistencia.
Como siempre, el material de los dos eventos estará en mi cuenta de GitHub, y algún anuncio habrá por acá.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez 
Author: "lopez" Tags: "Desarrollo Web, Javascript, NodeJs, Buen..."
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 05 Jul 2014 17:19

En estos últimos años he estado practicando deliberadamente TDD (Test-Driven Development) y trabajo en proyectos personales usando el flujo de trabajo de esta disciplina casi todos los días (ver mis posts de TDD y los commits en GitHub) Y también he trabajado en proyectos profesionales, con y sin TDD. Y luego de tanto código y proyectos, pienso que ya tengo un panorama de cuáles son los valores que agrega TDD a un proyecto que tenga desarrollo de software y cuáles son los problemas que podemos tener si no usamos TDD..

Primero, hay que recordar que un proyecto profesional puede ser más que programar código: he escrito que un proyecto BUENO es el que resuelve un problema (ver Un Buen Proyecto). No es solamente programar código, y menos programar código como nos parece o nos gusta. Lo importante es solucionar el problema que tiene quien nos contrata como equipo o como desarrollador individual.

Hecha esa aclaración ¿que es lo que vi de más valor siguiendo TDD, tanto en proyectos personales como profesionales? El primer punto de valor que veo como evidente, espero poder transmitirles el concepto, es:

TDD NOS EMPUJA A LA SIMPLICIDAD EN EL SOFTWARE QUE CONSTRUIMOS

Como cada vez que escribimos un test tenemos que pasarlo de rojo a verde con el código más simple, entonces esa simplicidad se va transmitiendo a lo que estamos construyendo.

Antes de seguir con el tema simplicidad, recordemos que no es sólo hacer TDD. Por ejemplo, tengo en gran importancia implementar casos de uso (ver TDD y Casos de Uso). Sin una serie de casos de uso a implementar, corremos el peligro de salirnos del carril y escribir algo que nos parece lindo, interesante, pero no soluciona el problema que tenemos que atacar en el proyecto.

Entonces, con TDD y guiado por los principales casos de uso, vamos diseñando un software. TDD es un proceso de diseño de software, no de escribir tests o de testing. TDD nos lleva a construir un software lo más simple posible, y los casos de uso nos guían hacia donde realmente esta el problema a resolver. Me gusta decir que aplicamos “baby steps”, hacia un diseño incremental de la solución (ver TDD y Baby Steps). No digo no hacer diseño de antemano: hago algo de diseño,  pero en la servilleta del desayuno, y apenas un poco. No pongo diseño imaginado en el código HASTA QUE NO LLEGUE EL TEST que lo amerite.

No olvidarse del otro importante paso: el refactor. Es ahí donde vamos a poner lo que conocemos para mejorar el código. Y es notable: TDD, como flujo de trabajo, nos va enseñando sobre diseño de código, de forma incremental. Al llegar un nuevo test, podemos ver que lo que habíamos escrito hasta entonces no sea lo óptimo, y refactorizamos la implementación interna. En este paso puede aparece la aplicación de patrones. Y eso es bueno: aparecen en un contexto, el de refactorización, no aparecen “del aire” o porque se nos ocurre a nosotros que hay que aplicar tal patrón. Recordemos que unos de los atributos de un patrón de software es el contexto donde se aplica. En la etapa de refactor podemos descubrir o poner de manifiesto ese contexto y ahí entonces reción aplicar el patrón. Si hacemos diseño de antemano, podemos caer (y lo he visto suceder) en la “patronitis”: agregar todos los patrones habidos y por haber, porque pensamos que son la mejor práctica. Hacer eso es una variante de “optimización prematura es la madre de todos los males”. Lo que nos va a enseñar TDD es que no hace falta pensar todo de antemano, rompiendo YAGNI. Lo que vamos creando con TDD en general va estar en “buena forma” para adaptarse a los nuevos casos de uso y nuevos tests que aparezcan. 

Y aca esta el otro valor que agrega, paralelo a la simplicidad: no solamente el código va creciendo con la simplicidad necesaria, sino que tambien esta en su mayor parte ajustado a lo que nuestros tests piden, no a lo que nosotros queremos o imaginamos que necesita tener nuestro código. El diseño del software en construcción, de esta forma, es como la confección de un traje a medida, que va calzando perfecto en cada iteración a lo que necesitamos implementar. 

Para que no todo sea cháchara en este post, pongo un ejemplo concreto, que ya he expuesto en otros posts (ver, por ejemplo, Desarrollando una Aplicación usando TDD). Supongamos que necesitamos devolver una lista de nuestros productos por categoría, digamos, en una API. ¿Qué hacemos en el controlador? He visto muchas veces que ya al primer test se le coloca un repositorio “mockeado” porque, claro, necesitamos el patrón repositorio ¿no?. Así nace la “paternitis”. NO: si somos consecuentes con el flujo TDD, lo más simple es ir entregando al controlador…. un LISTA DE PRODUCTOS. Solamente cuando tengamos más casos de uso, y veamos que la lista de productos la necesitamos en otros lados, vamos separando su existencia en otros componentes. He visto también que llegado al primer o segundo test, o aún antes, ya se está diseñando la base de datos para tener una tabla de productos y otra de categorías. Yo pregunto ¿quién, en qué el test, pidió eso? ¿qué test puso persistencia en el tapete? Muchas veces, NINGUNO. De nuevo, hay que ir implementando lo que nos pide el test, nada más, no hay que agregar nuestra propia “bajada de línea”, “ruptura de YAGNI”, como cuando pensamos “vamos a necesitar repositorio, vamos a necesitar persistencia” y entonces, necesitamos YA ponerlo y YA ponerlo como mock y así. Ese es el camino de romper la simplicidad de la que hablo.

De esta forma, el software que tengamos en construcción, crece como un organismo: de a poco, de forma controlada.

Seguiré con el tema del valor que agrega TDD, en los próximos posts: aumenta la calidad de código, permite la evolución y la adaptación al cambio, permite reducir la cantidad de bugs, permite arreglar los bugs detectados de forma más rápida, deja al proyecto en buena forma para que lo tomo otro equipo, etc.

Nos leemos!

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

 

Author: "lopez" Tags: "Arquitectura, Desarrollo Agil, TDD"
Comments Send by mail Print  Save  Delicious 
Date: Monday, 30 Jun 2014 13:30

En los dos últimos años estuve explorando las ideas de Storm (ver https://storm.incubator.apache.org/), implementándo alguna topología local en Node.js. Llegó la hora de practicar más C# y TDD (Test-Driven Development), con:

https://github.com/ajlopez/SharpStorm

El estado inicial del proyecto:

La idea es implementar bolt, spout y un builder de topologies. Leo en

https://storm.incubator.apache.org/about/simple-api.html

There are just three abstractions in Storm: spouts, bolts, and topologies. A spout is a source of streams in a computation. Typically a spout reads from a queueing broker such as Kestrel, RabbitMQ, or Kafka, but a spout can also generate its own stream or read from somewhere like the Twitter streaming API. Spout implementations already exist for most queueing systems.

A bolt processes any number of input streams and produces any number of new output streams. Most of the logic of a computation goes into bolts, such as functions, filters, streaming joins, streaming aggregations, talking to databases, and so on.

A topology is a network of spouts and bolts, with each edge in the network representing a bolt subscribing to the output stream of some other spout or bolt. A topology is an arbitrarily complex multi-stage stream computation. Topologies run indefinitely when deployed.

Como ven, en el proyecto por ahora están definidas las interfaces que espero por ahora tengan bolts y spouts, y un topology builder para armar una topología. Por ahora, quiero una implementación local (sin procesamiento distribuido). Luego, espero implementar el algoritmo de ACK que tiene Storm original, que permite saber cuándo un mensaje entrante quedó completamente procesado (incluso los procesos de los mensajes que produjo en el medio del proceso).

Próximos temas: revisar ISpout, IBolt, y como se arma una topología.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Proyectos de Código ..."
Comments Send by mail Print  Save  Delicious 
Date: Monday, 30 Jun 2014 12:26

Ya estuve experimentando con map-reduce en Node.js/JavaScript. Pero también es interesante implementar algo del algoritmo en C#, para practicar TDD (Test-Driven Development) y para aprender más sobre lo que implica implementar el algoritmo. El proyecto que inicié es:

https://github.com/ajlopez/SharpDoop

El estado del proyecto a hoy:

Tiene un proyecto de librería de clases, y el proyecto de test. Todavía no llegué a pensar en algo distribuido. Lo único que quiero por ahora es especificar el algoritmo de map, el de reduce, y enviarlo a que procese como un job, dentro de este proyecto.

Vean que hay entonces un MapReduceJob. Es la clase base que se encarga de ejecutar un map (un lambda o Action que toma clave, valor y va procesándolo) y un reduce (toma clave, una lista de valores de esa clave, y emite resultado). Gracias a C#, esas dos operaciones se pueden expresar como lambdas o como métodos delegados en un objeto más complejo. Por ahora, están funcionando los casos simples que planteo en los tests.

Como divertimento, armé también un MapProcessJob, que es una variante de map/reduce a discutir. En vez de procesar primero todas las claves, y luego pasarlas por el reduce, trata de hacer todo junto. En algunos casos de uso puede ser más eficiente, pero es un tema a discutir con más detalle.

Próximos temas: revisar más en profundidad la implementación y las ideas, como el map/process.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Proyectos de Código ..."
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 29 Jun 2014 20:16

Anterior Post

Hace ya año y medio que no escribo de este proyecto en C#, pero fui trabajando en él, y en la implementación paralela que tengo en JavaScript (de hecho, presenté algunos conceptos de ambos en la Smalltalks 2013 que se realizó el año pasado, en Rosario, Argentina).

El proyecto está en:

https://github.com/ajlopez/AjTalk

La estructura actual:

Veamos. Los proyectos son:

AjTalk: librería de clases, con la implementación de un compilador a bytecodes (y también a JavaScript), y un intérprete de los bytecodes compilados.

AjTalk.Compiler: un proyecto de consola que permite, usando el compilador mencionado en el proyecto anterior, generar código JavaScript.

AjTalk.Console: un REPL (Read Eval Print Loop)

AjTalk.Gui: una implementación sin terminar de ventanas

AjTalk.Tests: los tests que fui escribiendo, siguiendo el flujo de trabajo de TDD (Test-Driven Development)

El compilador a JavaScript creo que no lo voy a necesitar, porque en el último año he conseguido que el proyecto de BLOCKED SCRIPT

https://github.com/ajlopez/AjTalkJs

sea autosuficiente (ahora compila a bytecodes, pero también podría compilar a JavaScript; el tema que el intérprete de bytecodes me permite algunas operaciones más flexibles).

Y la implementación de ventanas (muy primitiva) la voy a sacar, para seguir por el camino de crear ventanas desde el propio AjTalk, en Smalltalk, accediendo a los tipos y objetos de .NET.

Un punto que me parece muy interesante (en ambos proyectos, el de C# y el de JavaScript) es tener una implementación modular: en vez de cargar una imagen con todo definido, poder definir módulos a cargar, como pasa en el ambiente Node.js. Los módulos estarían publicados en el NPM (El Node Package Manager), y cada cual podría indicar qué módulos necesita en su programa, en lugar de levantar todo Smalltalk.

Otro tema: en este proyecto de C# tengo implementado que pueda levantar más de una máquina AjTalk al mismo tiempo. E incluso puedo hacer que una máquina “ayude” a la otra. Por ejemplo, si la máquina A no tiene los métodos para compilar nuevos métodos, la máquina B puede ir en su auxilio. Así, la máquina A (y su imagen, que ya estoy grabando imagen binaria) puede mantenerse de tamaño pequeño.

Otra característica que tengo implementada: la capacidad de enviar un mensaje a un objeto, sin esperar una respuesta, un “fire and forget”. Y que el objeto destino pueda atender esos mensajes DE A UNO, como en los modelos de actores.

Tengo que revisar la implementación de objetos remotos (hoy basada en el viejo Remoting de .NET). Pero pienso que es una característica importante a mantener y explorar.

Bien, como ven, quedan multitud de temas para otros posts, como detalles de implementación de conceptos de Smalltalk, como Object, Class, ClassDescription, Behavior, MetaClass, etc.

Nos leemos!

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

Author: "lopez" Tags: ".NET, Smalltalk, C Sharp, AjTalk, Proyec..."
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 29 Jun 2014 12:24

Quería implementar un key-value store (como Redis) en C#, para ensayar algunas estructuras de datos y practicar TDD (Test-Driven Development). El proyecto que inicié es:

https://github.com/ajlopez/AjKeyvs

La estructura actual del proyecto:

Hay un proyecto de librería de clases, AjKeyvs, que contiene las colecciones que manejo en un repositorio. Lo interesante para este proyecto es implementar arreglos y conjuntos que puedan ser “sparse”, es decir que puedan tener claves muy diferentes. Ejemplo, tener una clave 1 (entero uno), y una clave 1000000 (entero un millon) y no tener que reservar un millon de lugares en el “arreglo”, sino solamente reservar lo que se usa. Y también tener un buen tiempo de acceso y modificación. Otras veces tendré claves String, con jerarquía, tipo “user”, “user:1”, “user:1:email”, etc. Y también quiero acceder rápidamente a ese tipo de estructura. Hay casos de uso que implican implementar conjuntos (con unión, intersección, etc), y en el caso de ser los elementos enteros, he implementado un conjunto donde prendo o apago un bit, de acuerdo a si el elemento correspondiente está o no está en el conjunto. Pero ya vendrá más detalle en próximos posts.

Si bien esa librería se puede usar in-process, también estuve armando un servidor, y un programa cliente. El servidor escucha y procesa comandos que le envían los clientes, enviándolos al repositorio de colecciones. Todas las colecciones se guardan en memoria. El tema persistencia me parece ortogonal a estos casos de uso. Veré si lo adoso a los comandos, o queda a responsabilidad del consumidor.

Y como es usual, hay un proyecto con los tests que fui armando siguiendo el flujo de trabajo de TDD.

Próximos temas: estructuras de datos, colecciones, comandos, concurrencia, etc.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, NoSQL, Proyectos de C..."
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 28 Jun 2014 16:50

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

Author: "lopez" Tags: ".NET, C Sharp, Programación Funcion..."
Comments Send by mail Print  Save  Delicious 
Date: Thursday, 26 Jun 2014 10:17

Desde la década pasada que me interesa Clojure, y desde siempre Lisp. Clojure está implementando sobre la máquina virtual de Java, pero también está implementado sobre .NET (que recuerde, usando Dynamic Language Runtime). La versión de Java compila a bytecodes Java. También hay una versión para JavaScript, llamada ClojureScript. La comunidad es muy activa, y ha traido un aire de renovación dentro de Java. Tiene características como la inmutabilidad de sus estructuras orientadas al trabajo en múltiples hilos evitando los problemas de lockeo y concurrencia. Tiene Software Transactional Memory, usando refs y transacciones,  pero ha sido menos usada por lo que veo. Han surgido frameworks web, y tiene un manejador de proyectos y dependencias Leiningen muy bien armado. Algunos enlaces en mis posts de Clojure.

Para practicar TDD (Test-Driven Development) y C#, he estado armando un intérprete (no un compilador a bytecodes), en .NET. Ver el proyecto en:

https://github.com/ajlopez/ClojSharp

El estado actual:

Tiene una librería de clases, otra de tests, y ya apareció un REPL (Read Eval Print Loop) sencillo como programa de consola.

En Lisp, una expresión se compone de un verbo y argumentos, expresados en una lista entre paréntesis. Por ejemplo una lista que al evaluarse devuelve la suma de 1, 2 y 3:

(+ 1 2 3)

Acá + (el signo más) es un símbolo que apunta a lo que en Lisp se llama una form, algo que recibe argumentos, opera con ellos y devuelve un resultado. Los argumentos que recibe un form en general se evalúan antes de serle entregados:

(+ 1 (- 3 4) 3)

Acá el primer argumento es una constante que vale uno, y el segundo argumento, antes de llegar al form de suma, ya es evaluado y vale –1 (menos uno). Pero hay forms que no necesitan evaluar los argumentos. Los reciben, digamos, en crudo. Se llaman special forms. Tengo implementados:

Y también tengo implementadas algunas forms (no especiales) como primitivas en C#. Muchas podrían ser implementadas en Lisp mismo, pero por ser tan básicas las implementé directamente en C#, usando TDD como es usual:

Próximos temas: la implementación de Machine, el Context, como se usa Parser y Lexer, más sobre evaluación de expresiones. Y mil temas más, como estructuras inmutables, macros, recursión optimizada, etc.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Clojure, TDD, Proyectos d..."
Comments Send by mail Print  Save  Delicious 
Date: Wednesday, 25 Jun 2014 13:25

Llegó la hora de escribir sobre el proyecto:

https://github.com/ajlopez/Aktores

Estoy implementando los primeros pasos hacia un modelo de actores, con pasaje de mensajes, tomando ideas de Akka. Ya había trabajado algo en Node.js, y en C# directo, teniendo actores que se mandan mensajes entre sí, pero esta vez quiero seguir el camino de Akka, paso a paso, como por ejemplo, tener nombres de actores, en un árbol, sistema de actores distribuidos, y la supervisión de agentes.

El estado del proyecto a hoy:

Veamos la implementación actual de actores:

Primero, un Actor es una clase abstracta, a implementar en cada caso por nosotros en cada sistema de actores que armemos. El resto del sistema no conversa con un actor directamente, sino a través de un ActorRef. Por ejemplo, para enviar un mensaje, hay un método Tell en el ActorRef. Internamente, tampoco lo envía a procesar al actor directamente, sino que cada actor tiene una Mailbox, y es a ese componente al que el ActorRef envia el mensaje. El objeto Actor es un objeto pasivo: no consulta la Mailbox directamente, sino que hay hilos de ejecución que van a ir consultando las tareas pendientes a hacer (como enviar un mensaje X a un actor A). Y el sistema internamente se asegura que al actor A sólo llegue a procesar UN mensaje por vez, para que el programador del actor no tenga que preocuparse por concurrencia desde múltiples hilos. Vean que, notablemente, el Actor no tiene una referencia a Mailbox. Pero eso es tema para próximos posts.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Proyectos de Código ..."
Comments Send by mail Print  Save  Delicious 
Date: Tuesday, 24 Jun 2014 18:41

Hace ya un tiempo, para practicar C# y TDD y explorar ideas de Erlang, inicié:

https://github.com/ajlopez/AjErl

La estructura de la solución:

Tiene el proyecto núcleo de librería de clases, el proyecto de tests, y estoy armando un REPL (Read Eval Print Loop) como programa de consola. Lo interesante de Erlang es que internamente tiene procesos livianos, implementados en la propia máquina virtual, que pueden comunicarse entre sí enviando y recibiendo mensajes inmutables. No pretendo implementar una máquina virtual de ese tipo, sino tener procesos en threads. Nunca van a llegar a ser tan rápidos como los de Erlang, pero es un primer “baby step” a explorar, antes de tratar de mejorar la implementación.

Los mensajes se pueden enviar a una cola por proceso (thread en este caso), y ya tengo implementado la aceptación de los mensajes, su rechazo y vuelta a procesar, como en Erlang nativo.

Pero hoy quería comentar brevemente la implementación de cómo transforma texto de entrada en expresiones y formas Erlang:

Hay un Lexer que devuelve tokens, y estos tokens tienen un valor y un tipo. Ya puedo reconocer un átomo (un nombre que comienza en letra minúscula), una variable, delimitadores, operadores, números enteros y reales, strings. El Lexer es consumido por un Parser, que tiene dos grandes métodos públicos: uno que parsea expresiones, usado desde el REPL, y otro que parsea lo que en Erlang se llama un form, sería como una definición de función en un módulo de Erlang. También hay formas que declaran el nombre del módulo, o que otras formas se exportan con nombre y cantidad de argumentos. En dichos módulos no se aceptan expresiones, sino solamente ese tipo de declaraciones form.

Si ven la historia de los commits, verán que no todo se desarrolló de antemano, sino que fue creciendo de a poco, a medida que me planteaba pequeños casos de uso a implementar.

Próximos temas: comentar la implementación de expresiones, forms, procesos como threads con mailbox para mensajes, y el REPL. Tengo que seguir trabajando en la implementación de mensajes y procesos distribuidos.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Proyectos de Código ..."
Comments Send by mail Print  Save  Delicious 
Date: Monday, 23 Jun 2014 16:42

Otro proyecto que tengo para practicar TDD (Test-Driven Development) y C#, es

https://github.com/ajlopez/SharpGo

Un intérprete (no compilador) del lenguaje Go de Google en C#. Como es usual, tiene un proyecto de librería y un proyecto de tests de la librería. Como el lenguaje Go es un lenguaje tipado, no puedo seguir el camino de armar un árbol de expresiones y evaluarla, como en RubySharp, PythonSharp y Mass, sino que el compilador tiene que tener varias fases, como en ScalaSharp, para ir detectando incosistencias de tipos, y declaraciones de tipos que todavía no se conocen al momento de analizar una sentencia o expresión.

Parte del proyecto, los nodos del AST que por ahora están implementados:

Los nodos que estoy armando del AST (Abstract Syntax Tree), se agrupan en dos grandes grupos:

- Nodos de Comandos, que deben producir comandos que se ejecutan.

- Nodos de Expresiones, que deben producir expresiones a evaluar, que devuelvan un valor. Tienen tipo.

Las comandos que declaran variables también tienen tipo. Por ahora, tengo todo dispuesto para comenzar a ir comenzando a:

- Declarar los tipos de algunas declaraciones de variables y funciones
- Controlar que los tipos sean los correctos, por ejemplo que a una variable entera no se le asigne un string
- Comenzar a emitir los comandos y expresiones adecuados

Como en otros proyectos, espero poder agregar acceso a los tipos y librerías propios de .NET. Un tema que tengo que examinar es cuánto del lenguaje Go puedo implementar. Un punto a estudiar: hay referencias a estructuras, que tengo que revisar si es posible mantener la semántica original o no en un lenguaje como C#. Parece interesante implementar canales, que ya hace unos años lo había implementado, tomando ideas de Go, en C# y en AjSharp.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Proyectos de Código ..."
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 22 Jun 2014 16:44

Ya algo escribí en este blog, pero es tiempo de presentarlo en sociedad. Hace unos meses, el año pasado, inicié el proyecto:

https://github.com/ajlopez/ScalaSharp

Un simple intérprete de un Scala simplificado, en C#. No pretendo implementar todo Scala ni tampoco que sea un compilador a CLR .NET. Mi intención es explorar una implementación de intérprete, alternativa, adoptando algunas características de Scala, sin llegar a sobrecargarlo.

Sin ser un programador Scala (ni aficionado ni profesional) mi impresión es que Scala, como lenguaje y librería, es algo así como “too much”, como demasiado, como “overwhelming”. La gente de Java lo adopta porque es más flexible, se necesita menos “boilerplate”, etc. Pero me parece como que Scala fue demasiado lejos. Habiendo programado en Java y en C#, pienso que este último, agregando pocas cosas (hace años delegados, lambdas, métodos de extensión, “generics” en la VM, y recientemente, entrada/salida asincrónica, async, await), ha sabido mantenerse saludable, sin grandes complicaciones. Vean qué fácil ha sido implementar LINQ, con evaluación “lazy” y demás.

En cambio, Scala me parece como que es “demasiado, todo junto”. Por lo que ví, la inferencia de tipos es una característica que no es tan necesaria en los proyectos reales. Y todavía no puedo aceptar que la lista de operadores de Scala ocupe más de una página web. Pero bueno, ése es el estado actual de la cosa. La gente de Scala está trabajando en una nueva implementación, llamada Dotty. Pero si recién lo están haciendo, luego de años de definición del lenguaje, tengo que declarar: “demasiado poco, demasiado tarde”.

Eso no obsta a que reconozca que Scala tiene grandes triunfos, aplicaciones no triviales como el Play Framework y Akka. Es Akka y Play lo que “va a salvar” a Scala. No se necesita tanto tantas características nuevas de lenguaje (apenas las que mencioné para C#) como librerías que organicen algunos temas (como la implementación de un servidor HTTP asincrónico o la distribución de mensajes entre actores distribuidos).

Para experimentar con un Scala simplificado, y para practicar deliberadamente TDD (Test-Driven Development) en C#, inicié el proyecto ScalaSharp.

Es un desafío para mí, porque no es un simple intérprete. Quiero implementar un AST (Abstract Syntax Tree) que detecte inconsistencias de tipos. En mis anteriores experiencias, como RubySharp, PythonSharp, y el lenguaje Mass, sólo era necesario armar un árbol de expresiones/comandos y evaluarlo. Ahora voy a tener que controlar que los tipos sean los adecuados. Por ejemplo, que una variable esté tipada, y que en sus asignaciones, la expresión a evaluar y asignar corresponda al tipo de la variable. Pueden ver algo del trabajo en progreso en:

https://github.com/ajlopez/ScalaSharp/tree/master/Src/ScalaSharp.Core/Ast

donde está el árbol de nodos tipado, versus los comandos y expresiones a ejecutar/evaluar:

https://github.com/ajlopez/ScalaSharp/tree/master/Src/ScalaSharp.Core/Commands
https://github.com/ajlopez/ScalaSharp/tree/master/Src/ScalaSharp.Core/Expressions

Próximos temas: detalles de implementación, control de tipos en el AST, transformación a comandos/expresiones. Lo bueno de hacerlo con TDD es que me permite ir implementado la solución a medida que defino los casos de uso.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Scala, Proyectos de C..."
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 21 Jun 2014 17:44

Anterior Post

En RubySharp puedo definir nuevas funciones (en realidad métodos del objeto actual) e invocarlas. Hay algunas funciones que ya están predefinidas en C#:

Veamos primero que toda función tiene que cumplir con la interfaz:

public interface IFunction
{
    object Apply(DynamicObject self, Context context, IList<object> values);
}

donde cada función, al aplicarse, recibe el objeto sobre la que es invocada como método, el contexto de variables (locales, argumentos, otros… ) actual, y una lista (posiblemente vacía) de argumentos.

Por ejemplo, la función puts está implementada así:

public class PutsFunction : IFunction
{
    private TextWriter writer;

    public PutsFunction(TextWriter writer)
    {
        this.writer = writer;
    }

    public object Apply(DynamicObject self, Context context, IList<object> values)
    {
        foreach (var value in values)
            this.writer.WriteLine(value);

        return null;
    }
}

Recibe: el objeto al que pertenece como método, el contexto, y una lista de argumentos. Cada uno de los argumentos ya lo recibe evaluado, y simplemente lo envía a un TextWriter, un argumento por línea. Vean que no imprime a la consola: el TextWriter se lo entregan cuando se crea esta función (veremos más adelante que se crea al crearse un objeto Machine). Esta inyección por constructor facilita el test de esta función predefinida, ejemplo:

[TestMethod]
public void PutsTwoIntegers()
{
    StringWriter writer = new StringWriter();
    PutsFunction function = new PutsFunction(writer);

    Assert.IsNull(function.Apply(null, null, new object[] { 123, 456 }));

    Assert.AreEqual("123\r\n456\r\n", writer.ToString());
}

Pero fue algo que nació no sólo de armar un test, sino de seguir el flujo de trabajo de TDD.

Veamos otro ejemplo de función predefinida, el require:

public class RequireFunction : IFunction
{
    private Machine machine;

    public RequireFunction(Machine machine)
    {
        this.machine = machine;
    }

    public object Apply(DynamicObject self, Context context, IList<object> values)
    {
        string filename = (string)values[0];
        return this.machine.RequireFile(filename);
    }
}

Esta vez, delega el trabajo de cargar un archivo de programa al objeto Machine que se le inyectó al comienzo.

Y finalmente, veamos el código de una función definida, con un cuerpo ya compilado de RubySharp:

public class DefinedFunction : IFunction
{
    private IExpression body;
    private IList<string> parameters;
    private Context context;

    public DefinedFunction(IExpression body, IList<string> parameters, Context context)
    {
        this.body = body;
        this.context = context;
        this.parameters = parameters;
    }

    public object Apply(DynamicObject self, Context context, IList<object> values)
    {
        Context newcontext = new Context(self, this.context);

        int k = 0;
        int cv = values.Count;

        foreach (var parameter in this.parameters) 
        {
            newcontext.SetLocalValue(parameter, values[k]);
            k++;
        }

        return this.body.Evaluate(newcontext);
    }
}

En este caso, se arma un nuevo contexto para que contenga a los argumentos de la función definida, con los valores que se pasaron ahora, y que recuerde igual al contexto desde donde fue definida. Observen que el contexto desde donde fue invocada (el Context context que recibe como parámetro Apply) no es usado. Hay una “closure” con el contexto en el que fue construida la función (el Context context que recibe en el constructor)

Hay más temas para explorar, como implementación de algunos comandos, la Machine que arranca todo, el REPL, etc.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, TDD, Proyectos de Có..."
Comments Send by mail Print  Save  Delicious 
Date: Wednesday, 18 Jun 2014 17:08

Anterior Post

Hace tiempo que no escribo de este proyecto:

https://github.com/ajlopez/PythonSharp

un intérprete en C# de un lenguaje tipo Python, con acceso a la librería de .NET.

Veamos hoy la estructura del proyecto principal de la solución:

Hay muchas cosas para agregar, pero lo que está contiene:

- Commands: Comandos a ejecutar ya compilados, como pass, for, if, …
- Expressions: También resultado de la compilación, a diferencia de los comandos producen un valor resultado. Hay expresiones para evaluar constantes, variables con nombre, éxpresiones aritméticas, llamadas a funciones/métodos, ..
- Compiler: Con un Lexer y un Parser que consumen un TextStream
- Language: Clases de implementación de algunos conceptos del lenguaje, como objeto dinámico, clase, módulo, …
- Functions: Implementación de funciones primitivas como dir, eval, exit, exec, …

Además de este proyecto hay:

- Proyecto de test: el proyecto principal fue desarrollando usando TDD paso a paso

- Proyecto de consola: que sirve para ejecutar scripts desde archivos o ingresar código desde una consola de comandos

Próximos temas: implementación del Lexer y Parser, Comandos, Expresiones

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, Python, Proyectos de C..."
Comments Send by mail Print  Save  Delicious 
Date: Tuesday, 17 Jun 2014 17:00

Anterior Post

Quería describir hoy algo de la implementación del REPL (Read Eval Print Loop) que implementé para SharpMongo en:

https://github.com/ajlopez/SharpMongo

Recordemos, SharpMongo es una base NoSQL basada en documentos, inspirada en MongoDB. Es trabajo en progreso, pero el núcleo ya está bastante implementado. El REPL es un utilitario de consola que sirve para probar algunos comandos.

Para implementar cosas como atender:

> db.people.insert({ Name: 'Adam', Age: 800 })
> db.people.insert({ Name: 'Eve', Age: 700 })
> show collections
people  

tuve que manejar un objeto Database que tuviera propiedades, y que esa propiedad (por ejemplo .people en el código de arriba) fuera una colección de documentos, incluso una no existente.

Curiosamente, la implementación de un objeto así está basada en los propios DynamicObject que tiene el núcleo de SharpMongo: los documentos que mantiene SharpMongo en memoria son objetos del tipo DynamicObject, y los objetos que maneje el REPL, también.

He aquí la implementación actual de DbObject

https://github.com/ajlopez/SharpMongo/blob/master/Src/SharpMongo.Language/DbObject.cs

public class DbObject : DynamicObject
{
    private DocumentBase dbase;

    public DbObject(DocumentBase dbase)
    {
        this.dbase = dbase;
    }

    public DocumentBase DocumentBase { get { return this.dbase; } }

    public override object GetMember(string name)
    {
        return new CollectionObject(this.dbase.GetOrCreateCollection(name));
    }
}

La forma de implementar la propiedad dinámica .people es redefinir el método que consigue una propiedad por nombre. En vez de basarse en el método de la clase madre, que mantiene un diccionario de las propiedades, en el código de arriba se devuelve una colección de documentos dentro de la base de documentos que estemos trabajando. Si ven el código y la historia del proyecto, todo esto fue programando usando TDD.

Próximos posts: implementación del objecto Collection en el REPL, parser, lexer, operadores

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, NoSQL, Proyectos de C..."
Comments Send by mail Print  Save  Delicious 
Date: Monday, 16 Jun 2014 10:35

Ayer comencé a codificar SharpBus, un simple procesador de mensajes inspirado en algunas ideas de Mule. Ver:

http://en.wikipedia.org/wiki/Mule_(software)

http://www.mulesoft.org/what-mule-esb

Como es usual, estoy usando TDD (Test-Driven Development), tratando de ir implementando pequeños casos de uso, de la manera más simple posible. De hecho, el proyecto es un ejercicio personal de TDD. Espero que alguna vez sea útil más allá de eso. Por ahora, es un ejemplo que quiero compartir de mi flujo de trabajo.

Pueden ver el avance en:

https://github.com/ajlopez/SharpBus

Las ideas principales a implementar son:

- Hay mensajes (Message) con un contenido (Payload) y propiedades (diccionario de nombre/valor)

- Hay flujos (Flow) que procesan mensajes

- Un flujo se compone de varios elementos

Los elementos pueden encadenarse en el flujo, y pueden ser:

- Un transformador (Transformer) que toma un contenido o mensaje completo y lo devuelve transformado

- Un procesador (Processor) que toma un contenido o mensaje completo y opera sobre él, por ejemplo, tomando acciones sobre algún dominio de negocio, pero sin transformarlo

- Un productor de mensajes/contenido (Input)

- Un consumidor de mensajes/contenido (Output)

- Un ruteador (Router) de mensaje/contenido, quien decide a qué próxima rama (Branch) en el flujo se deriva el mensaje/contenido

Y un flujo puede tener ramas con nombre. También habrá elementos que puedan emitir nuevos mensajes aparte del actual, y que puedan emitirlos a distintos flujos del sistema. Los productores de mensajes deberán poder correr en hilos de ejecución (Threads), en principio. Y habrá un conjunto de hilos (Pool de Threads) para atender los mensajes que se produzcan y derivarlos a los respectivos flujos.

Un flujo puede tomar un mensaje, y devolver una respuesta (un Request/Response), o puede tomar un mensaje, procesarlo, sin devolver una respuesta a quien lo envió.

A veces, un elemento necesitará el mensaje completo (Message) y otras veces le bastará operar sobre el contenido (Payload).

Los elementos, en el mundo de Mule/Java, son objetos. Notablemente, en C#, la forma más simple de implementar, es usando lambdas. Así, que siguiendo TDD, las primeras pruebas e implementación ha salido por ese lado. Pueden ver algunos tests simples en:

https://github.com/ajlopez/SharpBus/blob/master/Src/SharpBus.Core.Tests/FlowTests.cs

Por ejemplo, para enviar un contenido y recibir respuesta, en un flujo que está vacío, basta:

var flow = Flow.Create();

Assert.AreEqual(1, flow.Send(1));

Para enviar un contenido y transformarlo, es simple:

var flow = Flow.Create()
    .Transform(x => ((int)x) + 1);

Assert.AreEqual(2, flow.Send(1));

El .Transform espera una Func<object, object> que puede proveerse en el momento con una lambda. En un Mule clásico de Java 7, tendríamos que proveer un objeto que implemente una interface donde hay un método que transformar el Payload. Tengo que pensar si vale la pena tener un .Transform tipado tipo .Transform<T> (que recibe T y devuelve T), o .Transform<T, S> (que recibe T y devuelve S).

Vean que me decidí por configurar el flujo por código. En el ambiente Mule se acostumbra más configurarlo por Spring, escribiendo un XML. Me parece que es hora de explorar esta otra forma, y ponerla como “forma primera”, es decir, como la forma sobre la que todo lo demás se podría montar. Si alguien necesitara alguna vez un DSL (Domain-Specific Language) de creación de flujos, podría implementarse teniendo esta forma por código bien diseñada.

Siguiendo TDD, todavía no tengo un caso de uso de un Message (un mensaje completo, con contenido (Payload) y propiedades (Properties, un diccionario nombre/valor). Todo lo de arriba es procesar el Payload directamente.

Próximos temas: agregar Message con Payload, la salida de mensajes, el ruteo, el armado de ramas, etc..

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, TDD, Proyectos de Có..."
Comments Send by mail Print  Save  Delicious 
Date: Sunday, 15 Jun 2014 18:26

Anterior Post

Al fin comencé una nueva implementación de variables y su alcance en el lenguaje Mass. Mi idea es:

- Tener variables locales

- Sin necesidad de declararlas explícitamente

- Acceso al alcance “de afuera” si es necesario

La idea base es:

- Cualquier asignación a variable involucra al alcance local

Es decir, que si asigno

a = 3

en una función, esto refiere a una variable local a, en esa función. No importa si hay una variable a, externa a la función

Ver como ejemplo

https://github.com/ajlopez/Mass/blob/master/Src/Mass.Core.Tests/MachineFiles/Local.ms

# file variable
a = 1

define foo()
    a = 2 # local variable
end

foo()

La primer variable a es una variable del archivo en proceso. La variable asignada en la función foo, es una variabla local a ese entorno de función, y es distinta de la variable “de afuera”.

En cambio, si no asignamos la variable, y solamente la consultamos, no queda como variable local. Ejemplo:

https://github.com/ajlopez/Mass/blob/master/Src/Mass.Core.Tests/MachineFiles/Scope.ms

# file variable
a = 1

define foo()
   a # access file variable
end

foo()

En este caso, la función foo devuelve el valor de a “de afuera”, pues esa variable no ha sido asignada en la función en el momento de evaluar el valor de retorno.

¿Cómo modificar una variable “de afuera”, que no sea local? Bien, tema para próximo post. La idea: acceder al valor de una variable no local, tiene que ser implícito, sin necesidad de declarar nada adicional. PERO MODIFICAR su valor debe ser explícito: debemos poner algo para que se entienda “queremos modificar el valor de una variable no local”.

Nos leemos!

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

Author: "lopez" Tags: "C Sharp, Lenguajes de Programación,..."
Comments Send by mail Print  Save  Delicious 
Date: Saturday, 14 Jun 2014 17:42

Anterior Post

Veamos hoy cómo se arma un parser con GrammGen, usando código. La idea de GrammGen es definir cómo construir un árbol con las expresiones que detectamos en un texto, según el lenguaje que querramos implementar. Y que esa definición sea por código, no por una gramática escrita en texto, sino simplemente por código.

Presenté en el anterior post a un ejemplo de consola, que emplea a GrammGen. Un parser se define usando reglas. Las reglas indican:

- Cómo procesar los caracteres del texto
- Cómo formar entonces elementos del texto, como números, nombres, operadores

- Cómo ir armando desde esos elementos, expresiones, comandos que definamos para nuestro lenguaje a implementar.

En el ejemplo de calculadora

https://github.com/ajlopez/GrammGen/tree/master/Samples/Calculator

las reglas están definidas en el parser:

https://github.com/ajlopez/GrammGen/blob/master/Samples/Calculator/Calculator/ExpressionParser.cs

Veamos las primeras:

private static Rule[] rules = new Rule[]
{
   Rule.Or(' ', '\t', '\r', '\n').Skip(),
   Rule.Or('+', '-').Generate("Oper0"),
   Rule.Or('*', '/').Generate("Oper1"),
// ...

La idea es conseguir una Expression. La primera regla define que cualquiera (Rule.Or) de los elementos espacio, tabulación, retorno de carro, nueva línea, se de ignodrar (.Skip()). Se puede poner más de una regla de este tipo, por ejemplo, para definir comentarios que deben ignorarse del texto de entrada.

La segunda regla define que tanto + (el signo más) como (el signo menos) producen un terminal llamado Oper0. Se diferencian de los * (el signo por) y / (el signo de dividir) porque queremos tener precedencia entre los operadores.

Hay una regla para formar enteros:

Rule.Get("0-9").OneOrMore().Generate("Integer", MakeIntegerConstantExpression), 

El Rule.Get permite especificar un rango de caracteres, y luego, con la fluent interface definida, se le puede adosar el .OneOrMore(), que especifica que esa regla se puede aplicar una o varias veces. Cuando no se pueda aplicar más, termina generando un node llamado “Integer”. Pero en GrammGen, un node, además de tener un nombre, puede tener un objeto asociado. Al .Generate se le puede pasar como segundo parámetro una función que cree ese objeto. Lo que hace MakeIntegerConstantExpression es:

- Recibe el objeto que se formó con la regla, en este caso, un string con todos los dígitos concatenados que se fueron encontrando.

- Lo transforma a entero

- Devuelve un objeto ConstantExpression que representa a ese entero en el árbol a evaluar.

El objecto ConstantExpression lo definimos nosotros, no GrammGen. Nosotros tenemos la libertad de definir los objetos que queremos adosar en cada nodo del árbol que GrammGen va formando.

El código de este método entonces es:


   private static object MakeIntegerConstantExpression(object obj)
   {
       int value = int.Parse((string)obj);

       return new ConstantExpression(value);
   }

En los próximos posts veremos cómo se forman los nodos de operaciones binarias, cómo se trata la precedencia de operadores, cómo se implementa la recursión a derecha, y la evaluación de la expresión.

Nos leemos!

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

Author: "lopez" Tags: ".NET, C Sharp, GrammGen, Proyectos de C&..."
Comments Send by mail Print  Save  Delicious 
Date: Tuesday, 10 Jun 2014 11:58

Es tiempo de revisar mis resoluciones de Mayo:

- Trabajr en SimpleScraper, primeros casos de uso [completo] ver repo
- Continuar RuScript [pendiente]
- Continuar RustScript [parcial] ver repo
- Continuar SharpGo [completo] ver repo
- Continuar Distributed Messages in AjErl [pendiente]
- Mejorar Mass Language [pendiente]
- Continuar Aktores (implementar distribución de mensajes) [pendiente]

Adicionalmente, estuve trabajando en:

- Continuar ScalaSharp [completo] ver repo
- Comenzar SimpleApps, mi refinamiento de MyApps [completo] ver repo
- Continuar ClojSharp [completo] ver repo

Mis resoluciones para este nuevo mes, Junio de 2014:

- Continuar AjErl
- Continuar ScalaSharp
- Continuar SharpGo
- Poner alcance de variable en el lenguaje Mass
- Comenzar SimpleItems
- Continuar SimpleApps
- Continuar ClojSharp
- Continuar DictSharp
- Primer caso de uso distribuido en AjErl
- Primer caso de uso distribuido de Aktores
- Escribir Posts de C#
- Escribir Post de TDD
- Mejorar mi sitio personal

Nos leemos!

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

Author: "lopez" Tags: "C Sharp, Javascript, NodeJs, Programaci&..."
Comments Send by mail Print  Save  Delicious 
Next page
» You can also retrieve older items : Read
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader