Angel "Java" Lopez

NET, Java, PHP y Desarrollo de Software

This Blog

Syndication

Search

Tags

Community

Email Notifications

Archives

.NET

ASP.NET

Windows Form

VB.NET

C#

Sitios

Blogs

September 2011 - Posts

Aj​Script: Intérprete tipo Javascript en C# (2) Expresiones

Anterior Post

Como en otros intérpretes, una pieza clave es la Expression, algo para evaluar durante la ejecución de un programa. En Aj?Script (repositorio de código) tengo una IExpression:

public interface IExpression
{
    object Evaluate(IContext context);
}

Estas son las que tengo implementadas en el código actual:

Veamos un ejemplo de expresión simple, ConstantExpression:

public class ConstantExpression : IExpression
{
    private object value;
    public ConstantExpression(object value)
    {
        this.value = value;
    }
    public object Value { get { return this.value; } }
    public object Evaluate(IContext context)
    {
        return this.value;
    }
}

Un poco más interesante, VariableExpression, dado un nombre y un contexto devuelve el valor de la variable según su nombre:

public class VariableExpression : IExpression
{
    private string name;
    public VariableExpression(string name)
    {
        this.name = name;
    }
    public string Name { get { return this.name; } }
    public object Evaluate(IContext context)
    {
        return context.GetValue(this.name);
    }
}

A veces una expresión tiene uno o dos parámetros. Tengo UnaryExpression y BinaryExpression como clases abstractas. El código de BinaryExpression:

public abstract class BinaryExpression : IExpression
{
    private IExpression leftExpression;
    private IExpression rigthExpression;
    public BinaryExpression(IExpression left, IExpression right)
    {
        this.leftExpression = left;
        this.rigthExpression = right;
    }
    public IExpression LeftExpression { get { return this.leftExpression; } }
    public IExpression RightExpression { get { return this.rigthExpression; } }
    public abstract object Apply(object leftValue, object rightValue);
    public object Evaluate(IContext context)
    {
        object leftValue = this.leftExpression.Evaluate(context);
        object rightValue = this.rigthExpression.Evaluate(context);
        return this.Apply(leftValue, rightValue);
    }
}

Noten que el método Apply es abstracto. Una implementación concreta:

using Microsoft.VisualBasic.CompilerServices;
public class ConcatenateExpression : BinaryExpression
{
    public ConcatenateExpression(IExpression left, IExpression right)
        : base(left, right)
    {
    }
    public override object Apply(object leftValue, object rightValue)
    {
        if (leftValue == null)
            leftValue = string.Empty;
        if (rightValue == null)
            rightValue = string.Empty;
        return Operators.ConcatenateObject(leftValue, rightValue);
    }
}

Soy un programador perezoso: vean que uso los operadores de Visual Basic. Podría escribir una implementación directa en C#. Tengo todos los tests, listos en su lugar, para refactorizas esta expresión y otras.

No escribí todas estas expresiones de una vez. Un ejemplo: Escribí una clase Context usando tests, y entonces la clase VariableExpression usando tests. Agregué entonces el soporte de variables en el Parser, y evalué expresiones simples que usaran constantes y variables, dentro de nuevos tests. Uso ese patrón muchas veces: agregar una nueva clase de base (Context, Function…) con tests, agregar una nueva expresión (suma, invocación…. ) con tests, agrego el soporte de esa nueva expresión en el Lexer y en el Parser, con tests, y termino usando la nueva expresión en evaluciones de expresiones en tests.

Próximos tópicos: comandos, implementación de funciones, clausuras, “hoisting”, acceso a objetos nativos. Y ejemplos con AjScript.

Nos leemos!

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

Posted Mon, Sep 26 2011 10:29 by lopez | 1 comment(s)

Enlaces, Novedades y Recursos

Mi sitio personal comenzó como una forma de compartir recursos y enlaces de distintos temas, pero desde hace unos años directamente uso mi Delicious, dejando mi sitio para publicar material de cursos presenciales.

En mi blog en inglés he publicado colecciones de enlaces sobre temas que me interesan. Están bajo la categoría Links. Hay enlaces en inglés, pero también en español. Espero que algunos temas les sirvan, otros les resulten nuevos pero interesantes. En general, los publico primero en email privado en mi cliente principal (espero que alguien los lea, además de mi Tía Carlota ;-) y luego encuentran su curso para ser publicados en mi blog en inglés. He aquí los post publicados:

Closures
C# 5
Windows 8 and WinRT
Ruby
Lambda Calculus
Erlang
Node.js (2)
Haskell
Mock Objects
Scalability
MapReduce
TDD
Git
Domain-Driven Design
Game Development
REST
Javascript
HTML5
Windows Azure
Node.js
Object Oriented Programming

Para conseguir los tutoriales o videos de esa colección, ver el post mi Delicious sobre la forma en que “taggeo” estos enlaces.

Nos leemos!

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

Posted Sat, Sep 24 2011 11:49 by lopez | with no comments

Smalltalk y Javascript

Por décadas Smalltalk fue "la fragata bandera” de las ideas de objetos y clases implementadas en un lenguaje, ambiente de desarrollo e imagen viva. Pero ha sido un caso de “demasiado, y demasiado temprano”. Aparecieron Smalltalks diferentes, compañías que lo implementaban distintos, no había tanta comunicación en línea y masa crítica como para formar una comunidad que lo desarrollado. Se necesitaba mucho hardware, su ambiente de desarrollo era (y es) muy “lo hago a mi manera”, todo eso conspiró para que no llegara a la corriente principal de lenguajes usados hoy en día. Mientras tantos, nuevos lenguajes de los 90s (noten el paralelismo con el desarrollo de la web) aparecen Javascript hasta Ruby, tomando ideas de Smalltalk. Y son lenguajes más usados que Smalltalk. En este siglo, Javascript, Ruby, Python, CLR (la VM de .NET con varios lenguajes), JVM (la VM de java con scala, Groovy, Clojure (“look ma.. Lisp for the masses” ;-) siguen ganando momento. Con la emergencia de múltuples dispositivos, móbiles, tables, smart phones, distintos sistemas operativos, estos nuevos lenguajes están siendo desarrollados para ejecutar en muchos entornos diferentes. Y están soportados por una comunidad vibrante, con cantidad de buenos proyectos de código abierto que contribuyen a la popularidad y adopción de estas tecnologías. Vean como ejemplo a Node.js, una implementación en Javascript/Google V8 Engine del patrón reactor. Tiene cantidad de módulos que se montan sobre su implementación núcleo.

Los Smalltalkers clásicos preferiran sus entornos, pero es una realidad que el código Smalltalk podría aprovecharse de los lenguajes, máquinas virtuales y librerías existentes. Un camino promisorio: compilar Smalltalk a Javascript, y conseguir el sueño “run everywhere”. (Noten que Clojure (special Lisp over JVM and CLR) tiene una nueva rama: ClojureScript ver su rationale). Este post de hoy es una enumeración de proyectos que usan alguna variación de Smalltalk compilado a Javascript.

Está el ST2JS (Smalltalk to Javascript translator):

ST2JS - Smalltalk to Javascript translator
http://www.squeaksource.com/ST2JS/

ST2JS - Traductor de Smalltalk a JavaScript (Parte I) (Spanish)
http://diegogomezdeck.blogspot.com/2006/07/st2js-traductor-de-smalltalk.html

ST2JS - Traductor de Smalltalk a JavaScript (Parte II) (Spanish)
http://diegogomezdeck.blogspot.com/2006/07/st2js-traductor-de-smalltalk_28.html

Hay un Smalltalk Web Toolkit basado en el ST2JS (no pude encontrar el código fuente):

Smalltalk Web Toolkit (Smalltalks 2009)
http://www.slideshare.net/garduino1/swt-2009

Introducción a Smalltalk Web Toolkit (SWT) « CEIBO
http://ceibo.wordpress.com/2008/01/06/introduccion-a-smalltalk-web-toolkit-swt/ (with detailed mini examples of Smalltak to Javascript translations, like closures, blocks, etc)

Nicolas Petton tiene Amber (antes era JTalk), que crea archivos Javascript traduciendo código Smalltalk (tiene ejemplo ejecutando en Node.js):

ST 4U 133: Amber
http://www.jarober.com/blog/blogView?entry=3493610269

NicolasPetton/amber - GitHub
https://github.com/NicolasPetton/amber

Peter Fisk (creador VistaSmalltak, GWT Smalltalk, y ahora SilverSmalltalk) estuvo escribiendo Smalltalk usando Silverlight, herramientas de Google, y ahora, BLOCKED SCRIPT

Implementing Smalltalk’s Non-Local Returns in JavaScript « Silver Smalltalk
http://silversmalltalk.wordpress.com/2011/02/02/implementing-smalltalks-non-local-returns-in-javascript/

Smalltalk Classes in JavaScript « Silver Smalltalk
http://silversmalltalk.wordpress.com/2011/02/02/smalltalk-classes-in-javascript/

Vean el Lively Kernel, Javascript inspirado por Smalltalk, y JTalk (ahora Amber):

InfoQ: Smalltalk IDEs Come to the Browser: Jtalk, tODE, Lively Kernel 2.0
http://www.infoq.com/news/2011/08/smalltalk-in-browser

InfoQ: Dan Ingalls on the History of Smalltalk and the Lively Kernel
http://www.infoq.com/interviews/ingalls-smalltalk

Lively Kernel
http://en.wikipedia.org/wiki/Lively_Kernel

Hay una implementación de Smalltalk a Javascript, llamada S8, trabajo en progreso. Ver:

Blog de Leo De Marco: Lanzamiento de S8 en Smalltalking
http://leodemarco.blogspot.com/2011/09/lanzamiento-de-s8-en-smalltalking.html

Y sí, adivinaron! Hay Smalltalk a Javascript (y espero, a otros lenguajes dinámicos) en mi proyecto AjTalk (Work in Progress) (tengo que escribir post!). Estoy trabajando en cómo implementar algunas características como:

doesNotUnderstand for JavaScript?
http://stackoverflow.com/questions/3918920/doesnotunderstand-for-javascript

Is there an equivalent of the __noSuchMethod__ feature for properties, or a way to implement it in JS?
http://stackoverflow.com/questions/2266789/is-there-an-equivalent-of-the-nosuchmethod-feature-for-properties-or-a-way-t

Mis enlaces:
http://www.delicious.com/ajlopez/smalltalk+javascript

Gracias a @garduino por sus enlaces acerca de ST2JS y el Smalltalk Web Toolkit. Y a @leodmarco por su post aclaratorio sobre S8.

Se viene más Smalltalk a Javascript (usando AjTalk) ;-)

Nos leemos!

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

Posted Fri, Sep 23 2011 12:06 by lopez | 1 comment(s)

Filed under: , ,

Aj Script: Intérprete tipo Javascript en C# (1) Interfaces de Base

Estoy trabajando en implementar un interéprete C# llamado ABLOCKED SCRIPT un lenguaje tipo Javascript. El código (en progreso) está siendo publicado en:

https://github.com/ajlopez/AjScript

(el título de este post es Aj Script con un blanco, el Community Server me rechaza el título conteniendo AjScript al tomarlo por un script y lo bloquea).

Comenzó hace unos meses dentro de mi AjCodeKatas project en Google Code, pero hace unas semanas lo moví a GitHab: me permite tener más proyectos. En cambio, Google Code tiene un límite por número de proyectos. Por eso he puesto muchos pequeños proyectos dentro de AjCodeKata. Ahora, con GitHub no tengo esa limitación (hay límites de espacio no de cantidad de proyectos). Y con los forks públicos y los pull request, GitHub tiene su encanto.

La idea es tener un intéprete que tenga las “good parts” de Javascript. Estoy discutiendo conmigo mismo cuáles serán, por ejemplo, cómo estabilizar el tema de la herencia. Pero un punto clave a soportar es: acceso a objetos .NET nativos. Pueden escribir

var obj = new System.IO.DirectoryInfo(‘.’);

directamente en AjScript. Y pueden invocar código AjScript desde una aplicación .NET.

Pero ahora, quiero presentar las interfaces de base de este intérprete. Primero, IObject, la interfaz que todo objeto AjScript debe implementar:

 

public interface IObject
{
    IFunction Function { get; }
    object GetValue(string name);
    void SetValue(string name, object value);
    ICollection<string> GetNames();
    object Invoke(string name, object[] parameters);
    object Invoke(ICallable method, object[] parameters);
}

Vean que cada objeto tiene una propiedad Function: es la “clase” del objeto, la función usada al crearlo. Puede que lo cambie por Prototype.

Para mantener los nombres de las variables y sus valores, tengo una interfaz IContext:

public interface IContext
{
    IContext RootContext { get; }
    ReturnValue ReturnValue { get; set;  }
    void SetValue(string name, object value);
    object GetValue(string name);
    void DefineVariable(string name);
}

Noten que un contexto puede tener un contexto padre, para de esta forma tener contextos anidados. La propiedad ReturnValue es usada para detectar si hay un comando return ejecutado varios niveles adendro en la ejecución actual.

Cualquier método AjScript implementa ICallable:

public interface ICallable
{
    int Arity { get; }
    IContext Context { get; }
    object Invoke(IContext context, object @this, object[] arguments);
}

Noten que las funciones son IObject y ICallable con el poder adicional de poder crear un nuevo objeto:

public interface IFunction : ICallable, IObject
{
    object NewInstance(object[] parameters);
}

Próximos posts: ejemplos, closures, manejo de objetos nativos, lexer y parser, tests con TDD (escribí este intérprete usando TDD, tiene >80% de code coverage, podría mejorarlo).

Trabajo pendiente: implementar Function como “clase” con argumentos, prototype con propiedad .constructor, typeof, y las “clases” Javascript originales como Number, Date y otras; decidir qué características de  Javascript quedan “dentro” y cuáles quedan “fuera”. ¿Sugerencias?

Nos leemos!

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

Posted Mon, Sep 19 2011 11:07 by lopez | 2 comment(s)

AjFabriq en NodeJs (Parte 3) Una Aplicación Distribuida Simple

Anterior Post

Ejecutemos nuestra “killer app” (un simple contador) en dos nodos. En el repositorio, en examples\numbers, hay un programa appserver.js:

Es similar a mi ejemplo local. La diferencia es que el procesador de mensajes principal escucha por una puerta:

/**
 * Host.
 */
var host = ajfabriq.createLocalHost();
/**
 * Application configuration.
 */
 
var app = host.createProcessor('numbers', 'application');
var node = app.createProcessor('processor', 'node');
node.on('decrement', function (message) {
	console.log("Processing number " + message.number);
	
	if (message.number <= 1) {
		console.log("End Processing");
		return;
		}
		
	var number = message.number-1;
	
	this.post({ action: 'decrement', number: number });
});
host.listen(3000);
host.process({ application: 'numbers', node: 'processor', action: 'decrement', number: 10 });
En este código estoy usando ajfabriq.createLocalHost() en vez de .createProcessor(). Y host.listen(3000) comienza a aceptar mensajes desde otros nodos.

Ejecuto otro programa: appclient.js. Tiene los mismos procesadores locales:

/**
 * Application configuration.
 */
 
var app = host.createProcessor('numbers', 'application');
var node = app.createProcessor('processor', 'node');
node.on('decrement', function (message) {
	console.log("Processing number " + message.number);
	if (message.number <= 1)
		return;
		
	var number = message.number-1;
	
	this.post({ action: 'decrement', number: number });
});

Pero se conecta con el primer server y envía un nuevo mensaje:

var socket = new net.Socket();
socket.connect(3000, 'localhost',
	function() {
		host.connect(new ajfabriq.Channel(socket), true);
		socket.write(JSON.stringify({name : 'ajfmessage', message: { application: 'numbers', node: 'processor', action: 'decrement', number: 10 }}));
	}
);
	
ajfabriq.Channel es el canal bidireccional entre dos servidores ajfabriq.

Esta es la salida del segundo servidor:

Noten el intercambio de mensajes entre los dos servidores, al comienzo. Estan informando de sus procesadores de mensajes locales al otro servidor. De esta forma, cada servidor sabe qué mensajes puede procesar otro nodo.

Esta es la actividad del primer servidor luego del mensaje enviado por el segundo servidor:

Algunos de los números son procesados por el segundo servidor, y otros son ruteados al primer servidor. El ruteo es una simple elección al azar. Los objetos LocalHost tiene un nuevo método .post:

LocalHost.prototype.post = function (message) {
	var hosts = [ this ];
	
	for (var remote in this.remotes) {
		if (this.remotes[remote].accepts(message)) {
			hosts.push(this.remotes[remote]);
		}
	}
	var n = Math.floor(Math.random() * hosts.length);
	
	hosts[n].process(message);
};

Próximos pasos: un mejor ruteo, mejorar la comunicación de sockets (debo manejar mensajes JSON grandes, que pueden venir en varias comunicaciones, no en un solo read), logueo, más ejemplos de aplicaciones, ejemplos con más de dos nodos.

Nos leemos!

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

Posted Thu, Sep 15 2011 11:46 by lopez | with no comments

AjFabriq en NodeJs (Parte 2) Una aplicación local simple

Anterior Post 
Siguiente Post

Veamos de explorar cómo usar AjFabriq en NodeJs. Hay una simple aplicación:

https://github.com/ajlopez/AjFabriqJs/tree/master/examples/numbers

Implementa la última “killer application”: recibe un mensaje con un número, y postea un mensaje con ese número decrementado en uno ;-). Veamos có se define la aplicación:

/**
 * Module dependencies.
 */
 
var ajf = require('ajfabriq');

 

 

Incluí al directorio c:\Git en mi variable de ambiente NODE_PATH, y hay ahí un c:\Git\ajfabriq conteniendo mi repositorio git local de lo que estoy desarrollando. Pueden clonar el repo en el directorio node_modules donde está el NodeJs 5.x (see Playing With NodeJs (1) Running on Windows (and Azure), Jugando con NodeJs (1) En Windows (y en Azure)) .

AjFabriq define un objeto que expone algunos métodos. Esta es la manera de crear un procesador de mensajes que es local, y éste no es expuesto a otros servidor (en el próximo post explicaré una aplicación distribuida):

/**
 * Host.
 */
var host = ajf.createProcessor();

 

 

El procesador de mensajes (ver anterior post) puede contener otros procesadores, es un “composite”. El método aprocessor.createProcessor crea un nuevo procesador y lo agrega a su procesador padre:

/**
 * Application configuration.
 */
 
var app = host.createProcessor('numbers', 'application');
var node = app.createProcessor('processor', 'node');

 

 

El primer procesador, en la variable app, aceptará y procesará mensajes con la propiedad “application” teniendo como valor a “numbers”. Su procesador hijo procesará mensajes con la propiedad “node” con valor “processor”. De esta forma, podemos definir un árbol de procesadores de mensajes. Las propiedades del mensajes y sus valores forman entonces su información de ruteo, así que cada mensaje será enviado al procesador apropiado.

Pero ¿cómo definir la conducta del procesador hijo final? Para estar alineado con el procesamiento asincrónico de NodeJs, cada procesador hereda de un EventEmitter. Desde el anterior post, definí al Processor como una “subclase” de process.EventEmitter en el código de AjFabriq:

var EventEmitter = process.EventEmitter;
// ...
function Processor(name, kind)
{
	this.name = name;
	this.kind = kind;
	this.processors = [];
}
Processor.prototype.__proto__ = EventEmitter.prototype;

 

 

Ahora, podemos definir el procesador hijo final:

node.on('decrement', function (message) {
	console.log("Processing number " + message.number);
	
	if (message.number <= 1) {
		console.log("End Processing");
		return;
		}
		
	var number = message.number-1;
	
	this.post({ action: 'decrement', number: number });
});

 

 

El procesamiento de mensajes detecta una propiedad llamada “action”, y dispara el correspondiente evento. Noten el método emit en este código de AjFabriq:

Processor.prototype.process = function (message)
{
	if (this.processors == null || this.processors.length == 0) {
		this.emit(message.action, message);
		return;
	}
	
	for (var processor in this.processors)
		if (this.processors[processor].accepts(message)) 
		{
			this.processors[processor].process(message);
		}
}

 

 

 

Al final de mi “killer app”, un mensaje es enviado al procesador inicial:

host.process({ application: 'numbers', node: 'processor', action: 'decrement', number: 10 });

 

 

La salida:

Pero, esperen! ¿vieron el código de ‘decrement’ que mostré más arriba? Hay un:

this.post({ action: 'decrement', number: number });

 

 

No hay propiedad aplication, ni node. Y funciona igual. Si uno postea un mensaje a un procesador (en este caso al que está en la variable node), los procesadores padres llena las propiedades faltantes. Así, la propiedad application toma el valor “numbers”, y la propiedad node toma el valor de “processor”. Si quieren enviar un mensaje a otra aplicación, podemos poner explícitamente la propiedad correspondiente en el nuevo mensaje a enviar. Noten que la práctica recomendada es: no cambien el mensaje original. Puede que sea procesado por otros procesadores.

Para futuros posts: nuevas aplicaciones, un ejemplo distribuido

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com
http://twitter.com/ajlopez

Posted Wed, Sep 14 2011 6:33 by lopez | 1 comment(s)

AjLisp en Javascript (Parte 3) Define, Lambda y Closures

Anterior Post

Veamos la definición de nuevas formas en AjLisp, mi intérprete Lisp escrito en Javascript (github repository). Un forma especial clave en AjLisp es la define:

var defineForm = new SpecialForm();
defineForm.eval = function eval(list, env)
{
	var name = list.first().name();
	var value = list.rest().first();
	var body = list.rest().rest();
		
	if (isNil(body)) {
		value = evaluate(value, env);
	}
	else {
		value = new Closure(value, env, body);
	}		
		
	environment[name] = value;
	return value;
}

Se puede usar para definir datos simples globales. Mis primeros tests:

test("Evaluate Simple Expression with Atoms", function() {
	eval("(define one 1)");
	eval("(define two 2)");
	eval("(define three 3)");
	equal(eval("one"), 1);
	equal(eval("(quote one)").asString(), "one");
	equal(eval("(list one two three)").asString(), "(1 2 3)");
	equal(eval("(first (list one two three))"), 1);
	equal(eval("(rest (list one two three))").asString(), "(2 3)");
	equal(eval("(cons one (list two three))").asString(), "(1 2 3)");
});
		

Pero define está preparada también para recibir tres parámetros:

(define mapfirst (fn lst)
  (if (nilp lst)
    nil
    (cons
      (fn (first lst))
      (mapfirst fn (rest lst))
    )
  )
)

El primer parámetro es el nombre de la propiedad a definir en el ambiente (environment) global. El segundo parámetro es una lista de parámetros. El tercero es la forma a aplicar. Entonces, define se puede usar para definir nuevas funciones, formas. Es equivalente a

(define mapfirst (lambda (fn lst)
    (if (nilp lst)
      nil
      (cons
        (fn (first lst))
        (mapfirst fn (rest lst))
      )
    )
  )
)

Vean el lambda. Es una forma especial:

var lambdaForm = new SpecialForm();
lambdaForm.eval = function eval(list, env)
{
    var argnames = list.first();
    var body = list.rest();
    return new Closure(argnames, env, body);
}

Tanto define (con tres parámetros) como lambda terminan creando un Closure. La clausura recibe una lista de nombres de argumentos, un ambiente (closure environment) y un cuerpo. Entonces, cuando un closure se evalúa:

function Closure(argnames, closureenv, body) {
	body = new List(doForm, body);
	
	this.eval = function(args, environment) {
		var newenv = makeEnvironment(argnames, args, closureenv);
		return evaluate(body, newenv);
	};
}
	
Closure.prototype.evaluate = Form.prototype.evaluate;
Closure.prototype.apply = Form.prototype.apply;

La parta clave es el .eval: la evalucación de closure emplea un nuevo environment, basado NO EN EL ACTUAL, sino en el closureenv, el ambiente recibido en el constructor cuando la clausura fue creada. Esta es una típica implementación en un intérprete Lisp.

Próximos temas a discutir en posts: flambda, mlambda, evaluación de macros, y el parser.

Nos leemos!

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

Posted Tue, Sep 6 2011 12:05 by lopez | 1 comment(s)

Jugando con NodeJs (1) En Windows (y en Azure)

Hasta unas semanas atrás, la única forma de ejecutar NodeJs en Windows era bajar el código desde el repositorio en Github y compilarlo usando CygWin (otro caso de para tener la banana, hay que llevarse al mono también ;-). Ver:

Building node.js on Cygwin (Windows)
How to install Node.js on Windows

Pero ahora hay una alternativa: el equipo de NodeJs ha publicado una versión para Windows precompilada (0.5.4 y 0.5.5):

http://nodejs.org/#download
http://nodejs.org/dist/
http://nodejs.org/dist/v0.5.4/node.exe
http://nodejs.org/dist/v0.5.5/node.exe

(Hay una nueva versión http://nodejs.org/dist/v0.5.5/node-186364e.exe)

Estoy usando la 0.5.4. Luego de bajarme el exe, ejecuto un simple programa de demo que usa Socket.IO:

Node puede extenderse con módulos escritos en Javascript. El mensaje de arriba me avisa que me falta en módulo SocketIO. El probrama npm es el manejador de paquetes más usado de NodeJs, pero no hay una versión Windows (aún):

how can i do npm on windows!

Así que me bajé el módulo y sus dependencias, como dice:

Node.js on Windows: Who Needs NPM?

¿Dónde están las URLs de las dependencias y sus repos? Pueden ver en:

http://search.npmjs.org/

Me bajé algunos módulos, quedando ahora:

Están en el subdirectorio donde reside el node.exe. El archivo principal a leer y estudiar en cada módulo es su declaración Package.json. Ejemplo, éste es el manifiesto para Socket.IO:

{
    "name": "socket.io"  , 
    "version": "0.7.9"  ,
    "description": "Real-time apps made cross-browser & easy with a WebSocket-like API"  ,
    "homepage": "http://socket.io"  , 
    "keywords": ["websocket", "socket", "realtime", "socket.io", "comet", "ajax"]  , 
    "author": "Guillermo Rauch <guillermo@learnboost.com>"  , 
    "contributors": [        
	{ "name": "Guillermo Rauch", "email": "rauchg@gmail.com" }      , 
        { "name": "Arnout Kazemier", "email": "info@3rd-eden.com" }      ,
        { "name": "Vladimir Dronnikov", "email": "dronnikov@gmail.com" }
     ]  ,
     "repository":{
	    "type": "git"      , 
        "url": "https://github.com/LearnBoost/Socket.IO-node.git"    
     }  ,
     "dependencies": {
        "socket.io-client": "0.7.9"      ,
        "policyfile": "0.0.4"      , 
        "redis": "0.6.6"    
     }  ,
     "devDependencies": {
        "expresso": "0.7.7"      ,
        "should": "0.0.4"      , 
        "assertvanish": "0.0.3-1"
    }  ,
     "main": "index"  , 
     "engines": { "node": ">= 0.4.0" }
}

Cuando tuve todos los módulos, puse el valor de la variable NODE_PATH apuntando al directorio padre de todos los módulos, y ejecuté la aplicación de nuevo:

Triunfo de la mente sobre la materia! ;-) Este fue mi primer manera de ejecutar un programa. Pero recomendaría la alternativa: poner todos los múdulos en un subdirectorio llamado node_modules:

De esta forma, no necesitamos la variable NODE_PATH. Yo uso esa variable porque alguno de mis módulos están en desarrollo en otros directorios. Pero si tienen un subdirectorio node_modules, NodeJs (pienso que desde versión >0.5) busca en ese subdirectorio los módulos requeridos Y TAMBIEN en el NODE_PATH. Entonces puedo usar node_modules directamente y poner adicionalmente NODE_PATH=c:\Git apuntando donde está mi módulo AjFabriq en desarrollo. NodeJs encontrará Socket.IO en el subdirectorio node_modules, y a mi AjFabriq en c:\Git\ajfabriq.

Si tienen problemas con las dependencias, lean el post de @cibrax:

Running the “Express” web development framework on Node for Windows

Ahí explica cómo usar un clon de npm escrito en Python para instalar nuevos módulos y dependencias de NodeJs.

Hasta hay una manera de ejecutar NodeJs dentro de IIS. Vean el post de @shanselman:

Installing and Running node.js applications within IIS on Windows - Are you mad?

Una alternativa interesante a NodeJs que ejecuta en ASP.NET:

Asynchronous scalable web applications with real-time persistent long-running connections with SignalR

Bueno, ¿y si necesitamos ejecutar NodeJs en Azure? Me gustaría escribir un post sobre el tema, pero ….  @ntotten ya me robó la idea ;-). Lean:

NodeJS on Windows Azure

Otros posts sobre NodeJs y Azure:

Node.js, Ruby, and Python in Windows Azure: A Look at What’s Possible | MIX11 | Channel 9
http://channel9.msdn.com/Events/MIX/MIX11

Node.js, Ruby, and Python in Windows Azure: MIX Talk
http://blog.smarx.com/posts/node-js-ruby-and-python-in-windows-azure-my-mix-talk

Posts relacionados sobre NodeJs:

Node.Js: Links, news, Resources (2)
Node.Js: Links, news, Resources (1)
Playing with Node.js, Ubuntu, Sqlite3 and node-Sqlite
Jugando con Node.js, Ubuntu, Sqlite3 y node-Sqlite

Mis enlaces:

http://www.delicious.com/ajlopez/nodejs

Mas jugando con NodeJs en futuros post.

Nos leemos!

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

Posted Fri, Sep 2 2011 11:45 by lopez | 1 comment(s)

Filed under: , ,