El próximo 21 de julio (de 18:30 - 20:00; GMT -3; horario de Buenos Aires) el amigo Juan Gabardini, viejo compañero de aventuras, estará presentando un Webinar (un seminario via web) patrocinado por la buena gente de Kleer.
El tema es el uso de casos de prueba basados en ejemplos utilizando FitNesse, la plataforma de pruebas de aceptación basada en wikis creada por el tío Bob Martin y amigos en base al FIT original de Ward Cunningham (ambas herramientas de código abierto y gratuito).
El evento es en línea y gratuita, pero los interesados deben registrarse porque hay una cantidad máxima de asistentes (aunque no se bien cuál).
La sesión se presentará utilizando GoToMeeting, un servicio de conferencias en línea de Citrix que soporta Windows y Mac OS y utiliza un cliente que se descarga al momento de la conexión, por lo que recomiendo conectarse unos 10 minutos antes para estar seguros de que todo funciona correctamente.
El temario, según la invitación, es el siguiente:
¿Cómo logramos que los requerimientos sean claros tanto para los usuarios como para los desarrolladores?
¿Cómo lograr validar continuamente y con bajo costo que el producto cumpla con los requerimientos?
Veremos las especificaciones por medio de ejemplos, una técnica utilizada para lograr estos objetivos, y Fitnesse, una herramienta libre que soporta la técnica.
Fitnesse permite escribir los ejemplos (requerimientos) como tablas o historias, y ejecutar automáticamente estos ejemplos contra la aplicación, informando si la aplicación cumple con los resultados esperados.
(gracias a José Romaniello por descubrirme este interesantísimo lenguaje)
Cobra es un lenguaje multi-plataforma y multi-paradigma que combina una cantidad de características sumamente interesantes.
Es obra de Charles Esterbrook, y su autor describe sus principios de diseño de la siguiente manera:
Programación rápida y expresiva
Rápida ejecución
Tipado estático y dinámico
Calidad soportada a nivel del lenguaje
Por supuesto que suena ambicioso y vendedor, pero en principio, es bastante realista. Veamos cómo se soporta cada cosa:
Programación rápida y expresiva
Cobra tiene una sintaxis basada en Python (sobre todo) y Ruby, lo que lo hace mucho más legible que los lenguajes "con llaves y punto y coma". Entre otras cosas, en Cobra los bloques se determinan por indentación, las listas y diccionarios se pueden declarar como literales, hay comandos como print y assert de uso sencillo y poderoso, la manera de iterar y dividir listas es simple, y mucho más.
Un ejemplo rápido de la sintaxis, con la definición de una clase:
class Person
"""
Declaración de una clase. Este comentario documenta la clase misma
"""
var _name as String # Declara variables de instancia (no estáticas)
var _age as int
cue init(name as String, age as int) # Inicializador (constructor)
base.init
_name = name
_age = age
def sayHello # Métodos
# Los corchetes interpolan valores en las strings
print 'Hello. My name is [_name] and I am [_age].'
def divide(i as int, j as int) as int
""" Este comentario documenta este método """
assert j > 0 # Si el divisor
return i / j
Rápida ejecución
Esto es logrado a través del uso de tipos estáticos con inferencia permanente, sin perder las capacidades dinámicas para los casos necesarios.
La implementación actual de Cobra utiliza la Infraestructura Comun de Lenguajes (CLI) de .NET/Mono, por lo que el compilador genera código intermedio (IL) que a su vez es es llevado a código nativo por el motor de ejecución de .NET/Mono como en otros lenguajes.
Tipado estático y dinámico
La mayor parte de la resolución es estática y en tiempo de compilación, mientras que siempre que haga falta puede utilizarse resolución dinámica en tiempo de ejecución, basada en Reflection de .NET y apoyándose en técnicas específicas de optimización.
Veamos un ejemplo sencillo de una misma función declarada estáticamente:
def add(a as decimal, b as decimal) as decimal
return a + b
... o dinámicamente:
def add(a, b) as dynamic
return a + b
En la práctica, no son la misma función, ya que la primera opera solamente con números decimales, y la segunda con cualquier tipo que soporte la operación suma.
Obviamente la primer función es más rápida, ya que se verifica y compila, y no requiere más recursos que los operandos de un largo conocido (decimal), mientras que la segunda, al resolverse dinámicamente, es verificada en tiempo de ejecución y requieres más recursos para la conversión de parámetros, etc.
Por otro lado, contar con ambas variantes es lo ideal, ya que podemos aprovechar el contrato estricto de los tipos estáticos para gran parte de la aplicación, pero con la flexibilidad de los dinámicos para las porciones que son más variables, o para facilitar el prototipado.
Nótese que el soporte a tipos dinámicos de Cobra, comparado con el de C# o VB (a partir de .NET 4), es sintácticamente más sencillo, mucho más integrado a nivel del lenguaje.
Calidad soportada a nivel del lenguaje
Cobra soporta contratos de código (algo proveniente de Eiffel que .NET 4 soporta parcialmente), pruebas unitarias, comentarios para documentación y verificación de valores nulos en tiempo de compilación, todo como parte de su sintaxis.
Veamos como las pruebas unitarias quedan embebidas directamente como parte de un método:
class Utils
shared
def countChars(s as String, c as char) as int
"""
Returns the number of instances of c in s.
"""
test
assert Utils.countChars('', c'x') == 0
assert Utils.countChars('x', c'x') == 1
assert Utils.countChars('X', c'x') == 0 # case sensitive
assert Utils.countChars(' ! ! ', c'!') == 2
body
count = 0
for ch in s
if c == ch
count += 1
return count
Las aserciones, además, pueden usarse en cualquier parte del código, y arrojan una excepción con información útil para depuración si no se cumplen (no son un IF).
Los contratos embebidos en el código permiten especificar pre y post-condiciones a los métodos, garantizando la consistencia antes de entrar y después de retornar el valor final. Por ejemplo:
class Customer
var _contacts as List<of Contact>
get contacts from var
def addContact(contact as Contact)
require # Arroja excepción si algo no se cumple ANTES de entrar
contact not in .contacts
contact.name
contact.customer is nil
ensure # Arroja excepción si algo no se cumple DESPUES de salir
contact.customer == this
.contacts.count = old .contacts.count + 1
body
contact.customer = this
_contacts.add(contact)
Y otra característica muy buena de seguridad es que los parámetros o tipos que pueden recibir nil (llamado como en Smalltalk o LISP), son los que se declaran como tales, agregando al sufijo "?" al tipo, como en:
def bar(s as String?)
if s # Es igual que preguntar "if s is not nil"
print Utils.countChars(s, c'x')
Cobra está escrito en Cobra
Una característica más que quiero remarcar es que este lenguaje está escrito sobre si mismo. Por supuesto hay una parte del compilador escrita para la plataforma nativa (C# en este caso), pero el resto está escrito en Cobra mismo, lo que hace que el lenguaje tenga un nivel de depuración y prueba mayor que otros que se construyen generalmente sobre lenguajes de más bajo nivel. Esto está sucediendo en otros lenguajes a posteriori, como en el caso de PyPy o Rubinius, pero en Cobra fue un principio de diseño.
Personalmente me parece uno de los lenguajes "experimentales" más interesantes y completos que he visto en los últimos tiempos, en parte porque se apoya en una plataforma que ya ofrece muchos servicios, y en parte por algunas de sus características maduras que y las herramientas con que ya cuenta (compilador, ejecutor de pruebas unitarias, generador de documentación, coloreador de sintaxis, etc).
Y también cuenta con soporte parcial en algunas IDEs y editores:
Visual Cobra es un complemento para Visual Studio que reconoce y colorea la sintaxis.
Naja es una IDE completa escrita en Cobra que ademas del coloreo de sintaxis tiene soporte para lista de tareas basada en comentarios, soporte para proyectos y un diseñador de formularios que genera código Cobra.
Y si uno prefiere un editor de texto hay muchos para los cuales hay complementos para soportar la sintaxis, incluyendo gedit, Notepad++, UltraEdit, Vim y TextMate (el que estoy usando yo), y mucho más para elegir según la plataforma que cada uno usa. Y para cualquier otro caso existe un detalle de las palabras clave y modificadores, de manera que en cualquier editor se puede partir del soporte para Python y cambiar estas listas.
Finalmente, dejo este video de la presentación de Esterbrook en el Lang .NET Symposium 2008. Aunque la implementación del lenguaje maduró bastante desde entonces, muchos de los principios siguen igual.
Apple realizó su conferencia principal para desarrolladores, como todos los años, e imagino que la mayoría ya debe haber visto al menos algún compilado de la sesión de apertura, en la que se lanzaron Mac OS Lion, iOS 5 y iCloud, entre otras cosas.
Para quienes no lo vieron, dejo al final el video de esa sesión completa, aunque advierto que dura 158 minutos (casi 2 horas).
Si no tienen tiempo, pueden buscar en la web alguno de los compilados que muestran los anuncios más sobresalientes. Los hay super-comprimidos de 60 segundos, y algunos más detallados de unos 10 minutos.
Sin embargo, quienes quieran abundar en más información, no menos, ya pueden ver en video todas las sesiones (un centenear) de la conferencia, incluyendo algunas que captaron mi interés como (mi usual lista arbitraria; el sitio requiere un usuario gratuito registrado):
En esa sesión mi par es Diogenes Moreira, amante de la Orientación a Objetos que a pasado por múltiples tecnologías desde Cobol y PowerBuilder hasta Java y C#, siempre con su corazón cerca de Smalltalk.
Diogenes trabaja actualmente para Ilon SA y aunque tiene múltiples responsabilidades no deja de programar junto a su equipo. Participó en varios proyectos de código abierto, incluyendo colaboraciones para Pharo.
Nos conocemos por amigos comunes y por el grupo Agiles de Buenos Aires, y casualmente durante una de las reuniones mensuales de éste nos escapamos un rato a grabar este video en que hacemos algunos ejemplos con Seaside, un framework web para Smalltalk.
Como acompañamiento del video, dejo esta presentación de Esteban Lorenzano, en la que se recorren varias de las características que Diogenes comenta mientras escribimos los ejemplos:
Sin más preámbulos, el video, que dura aproximadamente 35 minutos. Estoy usando un servicio que brinda mucho mejor calidad de video (sobre todo para el código), pero tengan paciencia porque el reproductor puede tardar varios segundos (a veces casi un minuto) en empezar.
El infatigable equipo detrás de Heroku (la plataforma como servicio recientemente adquirida por Salesforce.com) está sumando a su infraestructura, creada inicialmente para simplificar el despliegue de aplicaciones Ruby (Rails, Sinatra u otros frameworks) la capacidad de alojar aplicaciones para Node.js
Ya hablé antes sobre Node.js, y como esperaba, este es el año en que el modelo de aplicaciones JavaScript del lado cliente y servidor comienza a consolidarse. El que una plataforma madura y robusta como Heroku facilite la ejecución de este tipo de arquitecturas potenciará muchísimo su uso.
Algo interesante que están haciendo en Heroku, siguiendo su estilo de pensar no sólo la solución sino el flujo de trabajo completo de desarrollo, es agregar mayor nivel de soporte a operaciones desde la línea de comandos, que es el ámbito donde los desarrolladores tienen mayores posibilidades de interacción desde el principio de los tiempos.
Como describen en este post, están agregando soporte a operaciones desde la consola de comandos, que permiten ejecutar procesos aislados (cada una de las líneas siguientes inicia un proceso en una instancia virtual, llamadas dyno, totalmente nueva, ejecuta el comando y baja la instancia):
$ heroku run date
$ heroku run curl http://www.google.com/
$ heroku run rails console
$ heroku run rake -T
$ heroku run rails server
Por supuesto que levantar un servidor de Rails para que inmediatamente después termine no tiene gracia en la mayoría de los casos, por lo que existe una manera de empaquetar procesos en un archivo Procfile, que simplemente declara los componentes necesarios, como por ejemplo:
web: node web.js
worker: node worker.js
Que crea una aplicación Node.js con dos componentes (un servidor web escuchando tráfico externo y un servicio interno para procesos intensivos, un modelo clásico en aplicaciones en la nube).
La gracia de este modelo es el mecanismo de escalamiento. Una vez que una aplicación está desplegada de esta manera, para escalarla basta usar un comando como:
$ heroku scale web=10 worker=50
Scaling web processes... done, now running 10
Scaling worker processes... done, now running 50
Como siempre, esto es un resumen, y recomiendo leer el post original, seguido de la segunda parte (dos más están por llegar) donde se presenta en más detalle el soporte para Node, incluyendo también una excelente descripción de que es y que no es Node para los recién llegados.
Uno de los objetivos de HTML5 es unificar el manejo de media para todos los navegadores y plataformas, pero hasta ahora, por cuestiones de indefinición de estándares, por temas de apertura, licenciamiento o comodidad tecnológica entre los jugadores del mercado, esto no ha sido sencillo.
Para solucionar este problema, el prolífico John Dyer escribió (y liberó bajo licencia GPL v2/MIT) MediaElement.js
Se trata de un reproductor de audio/video en JavaScript, como su nombre indica, que soporta una multitud de navegadores (los que soportan HTML5 y los que no) y unifica mucho más el soporte de codecs para diferentes formatos de video.
Para simplificar el uso manteniendo el soporte entre plataformas, el reproductor utiliza el mismo API en todas, basado en los tags <audio> y <video> de HTML5, implementándolos en los navegadores que no los reconocen, delegando el soporte a reproductores en Flash o Silverlight, pero que emulan exactamente el reproductor nativo.
De esta manera, el uso de estos elementos es idéntico en todos los navegadores para el productor del contenido, y la adecuación se produce en el cliente, que probablemente ya tenga los complementos necesarios descargados. La ventaja principal es que la manera de interactuar con los activos de audio o video es siempre igual.
El siguiente cuadro muestra el soporte para todos los navegadores, y la manera en que se soportan dependiendo de la plataforma:
Como siempre, el soporte se limita más en los dispositivos móviles, sobre todo en iOS, pero nótese que los navegadores de escritorio están cubiertos por completo.
La instalación de MediaElement es muy sencilla y está bien descripta en el sitio. Del lado del cliente, básicamente se reduce a incluir esta biblioteca y hoja de estilos:
Y para incluir el reproductor, utilizando el caso más extremo para dar soporte completo a todo, este es el marcado HTML (obviamente sin necesidad de incluir todos los comentarios):
<video width="320" height="240" poster="poster.jpg" controls="controls" preload="none">
<!-- MP4 en Safari, IE9, iPhone, iPad, Android, y Windows Phone 7 -->
<source type="video/mp4" src="myvideo.mp4" />
<!-- WebM/VP8 en Firefox4, Opera, y Chrome -->
<source type="video/webm" src="myvideo.webm" />
<!-- Ogg/Vorbis en versiones viejas de Firefox y Opera -->
<source type="video/ogg" src="myvideo.ogv" />
<!-- Opcional: Agregar subtitulos para diferentes lenguajes -->
<track kind="subtitles" src="subtitles.srt" srclang="en" />
<!-- Opcional: Agregar capítulos -->
<track kind="chapters" src="chapters.srt" srclang="en" />
<!-- Ante-último recurso: sólo para navegadores sin HTML5 ni JavaScript -->
<object width="320" height="240" type="application/x-shockwave-flash" data="flashmediaelement.swf">
<param name="movie" value="flashmediaelement.swf" />
<param name="flashvars" value="controls=true&poster=myvideo.jpg&file=myvideo.mp4" />
<!-- El peor de los casos: dejo una imagen -->
<img src="myvideo.jpg" width="320" height="240" title="No tiene manera de reproducir video" />
</object>
</video>
El reproductor en si soporta diferentes estilos, puede controlarse programáticamente desde JavaScript, tiene montones de opciones como tamaño para el marco de video o audio, volumen, reproducción en bucle, subtítulos (incluyendo traducción automática via Google translate), y más.
Creo que para cualquiera trabajando seriamente en media en este momento este reproductor es una de las soluciones más completas disponibles.
Cada tanto la comunidad Alt.NET se pone de acuerdo para realizar un Open Space en Buenos Aires, como en muchas otras partes del mundo. Ya he cubierto ediciones anteriores en este blog, y ahora me toca informar sobre la organización de una nueva reunión.
Como suele ocurrir, hay mucha gente que está interesada pero aún no se ha acordado la fecha definitiva, aunque hay consenso en hacerla durante el mes de julio. Para votar por la fecha que prefieran los interesados, estamos utilizando este mecanismo:
¡No sean tímidos! Todo el que esté realmente interesado en participar puede elegir qué sábado le queda mejor. Tengan en cuenta que usualmente s desde las 9 de la mañana hasta las 6 de la tarde, con la interrupción del almuerzo que se hace in-situ. Es probable que el lugar sea Microsoft de Argentina, en Bouchard 710, 4to piso, Ciudad de Buenos Aires.
Y como siempre, aprovecho para recordar que además de estas reuniones presenciales que se organizan esporádicamente en distintas ciudades, el grupo Alt.NET Hispano organiza reuniones virtuales en forma semanal (a veces más de una por semana), que se anuncian en la lista de distribución y en el calendario de reuniones del sitio.
Estas reuniones quedan grabadas y pueden verse a demanda una semana o dos después de su ejecución, y el grupo ya lleva (a hoy) 73 reuniones que pueden verse en línea o descargarse desde el histórico de reuniones.
Rubinius es una implementación de Ruby que tiene la característica principal de estar escrito mayormente en Ruby.
La máquina virtual está escrita en C++ y utiliza LLVM para convertir el bytecode en el código nativo del procesador destino, pero el compilador de los bytecodes y la gran mayoría de las bibliotecas están escritas en Ruby. Este nucleo utiliza un recolector de basura muy optimizado y permite extensibilidad en C que soporta las mismas extensiones en este lenguaje que utiliza el intérprete estándar de Matz (conocido como MRI).
El siguiente diagrama muestra la distribución de componentes de Rubinius:
Uno de los desafíos de Rubinius siempre fue medir el nivel de compatibilidad contra la implementación de Matz, por lo que tempranamente empezaron a trabajar en RubySpec, una serie de pruebas que funcionan como la especificación del lenguaje, ya que éste no tenía una originalmente y por sus propias características de meta-programación, es especialmente complejo de validar.
Básicamente, Rubinius, hasta su última versión estable, soporta Rails, Rake, RSpec, Nokogiri, Mongrel y prácticamente todas las bibliotecas y frameworks hasta Ruby 1.8.x.
La novedad es que el equipo acaba de liberar la versión preliminar 2.0, que fundamentalmente soporta Ruby 1.8.7 y 1.9.2, y funciona bajo Windows, pero además utiliza un nuevo mecanismo de threading realista que aprovecha los múltiples núcleos de los procesadores modernos.
Adicionalmente, el equipo migró el repositorio a GitHub. Para los interesados en el desarrollo de lenguajes, vale la pena al menos pegarle una mirada.
Uno de los principios de diseño del framework .NET, o más específicamente del CLI (Common Language Infrastructure) es, como su nombre lo indica, permitir implementar fácilmente una variedad importante de lenguajes.
El CLI es una pieza estandarizada ante ECMA como un estándar abierto, y es lo que ha permitido la creación de implementaciones abiertas de .NET como Rotor y Mono.
Pero también ha permitido la implementación de muchos lenguages (más allá de Microsoft) que comparten todo el ecosistema de herramientas y bibliotecas disponibles.
Nemerle es uno de estos casos. Desarrollado en la Universidad de Wroclaw, Polonia, se trata de un lenguaje de tipos estáticos, casi un superset de C#, que soporta estilos de programación funcional y orientada a objetos, metaprogramación, lenguajes específicos de dominio y mucho más. Al estar basado en el CLI genéricamente, funciona en .NET y en Mono por igual.
Siendo un superset, es posible compilar (con un par de toques en el archivo .csproj) fuentes C# en Nemerle.
Dos de las características más distintivas de Nemerle son la inferencia de tipos y el uso de macros.
Veamos algunos ejemplos de código, con inferencia de tipos:
def d = Dictionary ();
d.Add ("Code and Beyond", 42);
foreach (s in args) {
...
}
Notese que no hace falta inicializar los tipos del diccionario, que son declarados y chequeados a partir del primer uso.
En el caso de las macros, pueden escribirse cosas como:
ExecuteReaderLoop ("SELECT nombre, apellido FROM personas WHERE nombre = $miNombre", dbcon,
{
System.Console.WriteLine ("Persona: {0} {1}", nombre, apellido)
});
que enmascaran la creación del SqlCommand y el SqlReader, la clásica iteración y la obtención de las strings para los dos campos leídos, pero es importante ver que es mucho más que una función de una biblioteca, ya que en este caso se está interpretando la string conteniendo la sentencia SQL y generando el código chequeado correspondiente.
Nemerle también tiene interpolación de strings más eficiente que en C#, ya que se ejecuta en tiempo de compilación, como en:
$"Me llamo $Nombre y tengo $Edad años."
donde las variables reemplazadas son chequeadas por el compilador, a diferencia de utilizar String.Format, donde se realizan en tiempo de ejecución.
Es muy interesante además la sencillez para definir Macros, que no tienen nada que ver con las de C, y son descendientes directas de las macros de LISP. Veamos este caso que define un bucle hacia atrás:
Actualicé la presentación con algunos cambios en los poquísimos slides y mejoré un poco mi parte de los ejemplos, centrándome más en Code First que es la parte que me interesa más.
Pero no tuve mucha suerte: esta semana entró en erupción el volcán Pehueye en Chile, provocando bastantes problemas allá primero y en Argentina también, sobre todo en Bariloche, pero llegando a provocar demoras o cancelaciones de vuelos en toda la región.
Así que me quedé sin asistir, pero decidí grabar la sesión en video y compartirla. No llegué a tiempo con el procesamiento y la subida del video, me parece, pero espero que mis colegas y amigos de Chaco hayan podido compartir el link con el público de allá. Por mi parte, lo comparto aquí con todos los demás.
A medida que el tiempo avanza este lenguaje de marcado y su ecosistema se hacen temas cada vez más centrales en el desarrollo de software en general.
El reciente anuncio de Microsoft de que Windows 8 soportará HTML y JavaScript como una posibilidad para desarrollar aplicaciones de escritorio sigue en la línea de muchos otros jugadores del mercado que apuntan fuertemente a estos estándares.
Les dejo a continuación una serie de recursos para prender más sobre HTML5.
Este Manual de HTML5 en español es un PDF de 11 páginas con una buena introducción a los elementos principales.
Finalmente este curso de HTML y HTML5 incluye varios tutoriales en video que pueden ser útiles para ver las cosas en acción.
En inglés
Como siempre hay más recursos en inglés, y este tipo de información técnica es muy consumible para los programadores, incluso si no están duchos en ese idioma.
Dive into HTML5 es un libro completo en línea que además está escrito usando este estilo de marcado. Desde el comienzo se nota el uso de Web Fonts (noten que si bien la tipografía del título parece un gráfico, el texto es seleccionable).
Los blogs de SitePoint (que también ofrecen algunos libros pagos pero económicos) tienen muy buena infomación en sus blogs, categorizados por contenido sobre HTML5 y CSS3.
W3Schools tiene un Tutorial que además sirve como una buena referencia en línea para buscar información sobre forms, tags, atributos y eventos.
Este post contiene básicamente el video de la sesión de David Heinemeier Hansson (DHH) en la RailsConf 2011 a mediados del mes pasado en Baltimore, Maryland, EEUU.
El video, por supuesto, está en inglés, pero me parece interesante compartirlo porque en la sesión DHH comparte sus ideas acerca de los objetivos en los cambios en Rails 3.1, incluyendo la idea de más carpetas y archivos vacíos (para ayudar en la organización), y los motivos de la cuestionada inclusión de CoffeeScript y SCSS (comentada previamente en otro post).
Específicamente menciona que Rails seguirá siendo una plataforma con opiniones fuertes, donde las configuraciones por omisión serán las que el equipo considera las más relevantes y útiles en el momento, aunque siempre podrán cambiarse (por ejemplo, basta comentar las dos líneas que incluyen saas y coffee-script en el gemfile).
Sobre el final, menciona pjax, una biblioteca que maneja el contenido completo de una página estática como si fuese ajax pero manteniendo las url apropiadas, dejando que el botón BACK del navegador funcione perfectamente. Esa puede ser una de las próximas inclusiones en Rails.
Finalmente llega la primer RubyConf a la Argentina, y con intenciones de atraer cierta audiencia latinoamericana y algunos presentadores internacionales.
Un traductor de bytecode YARV (basado en Ruby 1.9)
Una máquina virtual basada en V8 (el motor de código abierto de Google) conectando las partes
Sin embargo, estas tres partes pueden ser utilizadas en forma independiente o reemplazadas por otras. Así, ColdRuby puede compilar código Ruby a JavaScript para que lo ejecute un browser, o ser ejecutado directamente en Node.js (que utiliza V8 por debajo).
Para los que todavía suponen que hacer algo así en JavaScript es una locura porque puede ser muy lento, los invito a mirar este emulador de completo de una PC escrito en JavaScript por Fabrice Bellard (autor de QEMU entre otras cosas), que bootea un Linux (funciona bien en versiones actualizadas de FireFox y Chrome, al menos).
ColdRuby tiene unos cuantos detalles "raros" que surgen de las diferencias de diseño entre ambos lenguajes, como el modelo de herencia prototípica de JavaScript contra el usual, basado en clases, de Ruby. También hay detalles como la manera en que se mapean algunos tipos de datos, pero en todos esos sentidos se ha tratado de mantener la alternativa más pragmática para usos generales.
La promesa es poder ejecutar Ruby dentro del browser (algo que hasta ahora era posible solamente con la combinación de IronRuby y Silverlight), e interactuar entre ambos lenguajes.
El proyecto es temprano y todavia un tanto experimental, pero interesante.