lunes, agosto 27, 2007

Tras las vacaciones

Preparo un curso presencial para finales de septiembre, sobre .NET Remoting, servicios Webs y servicios corporativos (Enterprise Services = .NET sobre COM+).
Todavía tengo alguna duda sobre el formato (y por consiguiente, sobre fechas), pero lo más probable es que tenga formato de seminario de un día, en plan guerrilla (BYOL: bring your own laptop, o traiga su portátil) para abaratar precios. La documentación incluirá la "famosa" serie E, que estoy terminando ahora.
Coca Cola, cerveza y café, a cargo de IntSight...
(if you got the money, honey, we got your disease)

Etiquetas: , , , ,

jueves, agosto 23, 2007

LINQ, Freya, Miranda

El siguiente listado muestra otra de las características "experimentales" de Freya: los filtros de iteración.
for i in 2..Max div 2 : not Result[i] do
begin

// ... etcétera...
end;

Freya

FreyaSe trata de un pequeño fragmento del algoritmo de la Criba de Eratóstenes, implementado en Freya, y muestra el uso de iteración mediante rangos y filtros. El bucle recorre valores enteros entre dos límites, pero sólo entrega aquellos números que no han sido marcados como primos todavía. El compilador traduce esta instrucción for en un bucle for numérico "clásico" con una instrucción if/then anidada. ¿Para qué tomarse entonces la molestia?
  1. El minimalismo en lenguajes no es necesariamente bueno
Esa es una curiosa superstición, que se desenmascara mirando lo que ocurre con Java. En este lenguaje, el repertorio de constructores de tipos es muy limitados: nada de delegados, nada de enumerativos, tipos de valor los justos... ¿Traspaso de parámetros por referencia? ¡Anatema, pecador! Copie el valor a modificar en la primera entrada de un array de un solo elemento, y pase el array como parámetro. ¿Necesito seguir?
  1. La combinación de rango más filtro aumenta mucho la expresividad
Mi teoría es que, en este caso, una simple ojeada a la cabecera del bucle deja las intenciones muy claras. Si no me cree, piense que ha escrito un for con un if anidado, y que la instrucción condicional tiene un bloque de instrucciones relativamente largo. ¿Cuánto tiempo tardaría en averiguar si existe una cláusula else o si se trata de un simple if/then? Espero que coincida conmigo en que se trata de dos patrones algorítmicos muy diferentes.
Confieso, no obstante, que llegue a lo creo un buen diseño gracias a una confusión. Freya se está diseñando, desde el primer momento, mediante un método que podríamos llamar mutación, erosión y selección, siguiendo un patrón similar al que ocurre con los lenguajes humanos. La mutación puede ocurrir deliberadamente o por error. Por ejemplo, en los primeros días, cuando Freya se parecía muchísimo más a Delphi, escribí por error una declaración de variable "global" dentro de una sección de implementación. Pero me di cuenta enseguida de que podía reinterpretar la declaración como una variable de instancia privada. Este un ejemplo de mutación. Un buen ejemplo de erosión es la omisión del nombre de la clase en el constructor. Al principio, el constructor llevaba el mismo nombre de la clase, pero un buen día olvidé escribir el nombre... y me di cuenta que era innecesario. Naturalmente, la selección es el proceso posterior a estos errores: es cuando me digo "y vio Ian que era bueno".

Miranda

Miranda¿Cuál fue mi error inicial, en este caso? Freya ya tenía rangos, que permitían tres usos: el uso trivial en instrucciones case, como operandos en el lado derecho del operador in y como iteradores en la instrucción for... sin filtros en aquel momento. Cuando me di cuenta de la frecuencia de aparición de iteración más selección en los ejemplos, pensé en introducir algo parecido a las expresiones de Zermelo-Frankel. Este ejemplo pertenece a Miranda:
[ n | n <- [1..5] ; n mod 2 = 0 ]
Una expresión ZF, o list comprehension, en la jerga funcional, permite directamente las tres operaciones más importantes soportadas por LINQ: iteración, selección y proyección. ¿Por qué no sustituir ese desagradable dialecto llamado SQL (¡sí, SQL como lenguaje es malísimo!) por un formalismo más elegante? Tenga presente que en mi ejemplo, el filtro se ha aplicado a un rango, pero en realidad, Freya permite usarlo con cualquier iterador...
En realidad, se trata de dos errores. El primero, es que la combinación de iterador más filtro no es, hablando con propiedad, una expresión de Zermelo-Frankel completa, pues necesita la variable de iteración para tener sentido. La primera consecuencia es que la idea no puede trasladarse automáticamente al operador in. Para verlo, sólo intente escribir una expresión in sobre un iterador filtrado. Es cierto que estas expresiones de pertenencia no ganan mucho cuando el iterador es un rango numérico, pero tenga presente que Freya permite usar el operador in con cualquier tipo que publique un método Contains (sí, hay que ampliarlo todavía para que maneje el tipo IEnumerable a secas).

LINQ

The Missing LINQNo se trata, sin embargo, de un error grave: a pesar de no poder aplicarse directamente a las pruebas de pertenencia, el recurso sigue siendo útil para los bucles for, como ya he explicado, por lo que mantuve la idea. El segundo error es más interesante: ¿pueden realmente las expresiones ZF reemplazar a LINQ? Con las debidas extensiones... sí. Pero estamos perdiendo de vista algo muy importante. Mi idea, realmente, era poder compilar eficientemente las expresiones de este tipo. Ahora mismo, C# 3.0 permite escribir código como el siguiente:
List<int> lista = { 1, 2, 3, 4, 5 };
if (lista.Exists(x => x % 2 == 0))
{
// ... etcétera...
}
No se trata de LINQ directamente, por cuestiones sintácticas, pero sí es la base de la implementación de LINQ: la prueba de existencia se convierte en una llamada a un método que recibe un delegado (un puntero a método, al fin y al cabo). ¿Eficiencia de la llamada? Asquerosa. Sí, es muy expresivo, pero sería mucho más rentable expandir el bucle de búsqueda en línea... si éste no consumiese tanto espacio y no ocultase nuestras intenciones.
Imagine ahora lo que ocurrirá cuando LINQ esté disponible: en principio, le permitirá acrobacias más complicadas con la nueva sintaxis... al precio de convertir su aplicación en una lenta babosa caracolera. ¿Significa esto que LINQ es un error? ¡De ningún modo! Pero el motivo por el que LINQ tiene sentido no está siendo debidamente explicado por los evangelistas entusiastas de la idea que pululan por foros y bitácoras. Y no me di cuenta del problema hasta haber experimentado con la característica de Freya que acabo de explicar.

Code is data

OuroborosEl verdadero corazón y sentido de LINQ no son esas amaneradas imitaciones de la sintaxis de SQL... sino los árboles de expresiones. Seamos sinceros: si LINQ sólo se pudiese usar con estructuras en memoria como las listas, sería una porquería del tamaño de la suma de todos los libros impresos sobre Java. Sería una porquería porque no habríamos logrado nada compilando estas construcciones como llamadas a métodos de la biblioteca de clases. Excepto ineficiencia, claro...
¿Por qué hay que llamar, entonces, a métodos de la biblioteca de clases? Pues porque, en algunos casos, como deja entrever la publicidad sobre LINQ, estos métodos, en vez de recibir delegados asociados a métodos anónimos, exigirán que el compilador les pase esos misteriosos árboles de expresiones. ¿A qué tipo de datos pertenece el parámetro del método en la siguiente llamada?
sequence.Where(x => x % 2 == 0)
En la mayoría de los casos, se tratará de un tipo delegado, pero podría tratarse de un árbol de expresiones. En ese segundo caso, sería el propio compilador de C# (como muestra la beta de Orcas) quien debería crear una estructura en memoria que reflejase la estructura de la expresión lambda para pasarla como parámetro. Es un comportamiento importantísimo, pero muy poco documentado.
¿Para qué puede querer un método recibir un árbol de expresiones, en vez de un puntero a método? Motivos sobran. Por ejemplo, el método puede transformar el árbol en una cadena que represente una instrucción SQL para pasarla a un servidor SQL. O el método puede formar parte de la capa de comunicación con un servidor remoto, y enviar una versión serializada del árbol para que sea evaluado al otro lado de la red. Estos son los casos reales de uso de LINQ, no esas tonterías de manipulación de listas en memoria que muestran casi todos los ejemplos.
¿Se da cuenta que LINQ, hasta cierto punto, nos retrotrae a los tiempos en que estaba de moda considerar el código como datos? De hecho, ¡podemos convertir fácilmente un árbol de expresiones en código nativo ejecutable! Si usted guarda fórmulas para los gastos de envío en una base de datos, seguirá necesitando un pequeño analizador sintáctico para convertirlas en árboles de expresiones. Pero ya podrá delegar en el sistema la conversión del árbol en código. ¿No es estupendo?
Resumiendo: LINQ es una buena idea, pero está siendo mal explicada. El riesgo que se corre es que aparezcan aplicaciones que utilicen LINQ de forma incorrecta... como, efectivamente, sugieren la mayoría de los ejemplos disponibles, incluso de la propia Microsoft. En segundo lugar, una vez que se comprende este problema, se comprende también que existe una puerta abierta en el diseño de lenguajes para .NET. Puede que sea beneficioso aumentar la potencia expresiva de las operaciones sobre listas mediante una sintaxis especial, paralela a la de LINQ. O puede que lo indicado sea la optimización de las llamadas a determinados métodos de determinadas clases, ya sea por medio del compilador o por medio de alguna utilidad aplicada al ensamblado compilado... pues dudo que el JIT llegue a estos extremos.

Etiquetas: , , ,

lunes, agosto 20, 2007

Liaison

¿Es Pascal un lenguaje "verboso"? Depende de con cuál lenguaje lo comparemos, por supuesto, pero en términos generales, se puede decir que sí lo es, porque introduce mucha redundancia en determinadas construcciones sintácticas.
Eche un vistazo a la siguiente, por poner un simple ejemplo:
for i := 0 to 9 do
begin

WriteLn(i);
WriteLn(i * i);
end;
Parece un código tan claro que casi brilla, pero ¿adivina qué es lo que sobra? Le daré una pista: localice dos palabras reservadas consecutivas...
Y esto, ¿qué le parece?:
for i := 0 to 9
begin
WriteLn(i);
WriteLn(i * i);
end;
Efectivamente, he eliminado la palabra clave do por estar ubicada antes de un begin. En general, la penúltima sintaxis de Freya permite, como opción, eliminar los do y los then que van antes de instrucciones que empiecen con palabras reservadas. Esta medida es parte de un esfuerzo de limpieza de la sintaxis que se ha cargado también construcciones propias de Freya como for var, que antes indicaba que estaba teniendo lugar una inferencia de tipo para una variable local.
Una aclaración: dos palabras claves consecutivas no siempre indican redundancia. Sólo es así cuando la palabra clave sólo hace de "esqueleto", es decir, cuando su papel es evitar ambigüedades sintácticas.
¡Ah!, y si se pregunta por qué me preocupan ahora los lenguajes verbosos y la redundancia innecesaria: estoy harto de pagar precios astronómicos por la puñetera tinta de impresora, el tóner y el papel. Hay más razones, pero ésta es importante y me parece incluso suficiente...

Etiquetas: ,

sábado, agosto 18, 2007

Perú

Llegan malas noticias desde Perú. Si conocéis alguna forma de ayudar...

miércoles, agosto 15, 2007

Enigma

¿Qué son los números complejos? Rostros que imaginamos en la Máquina de Turing.

La frase parece un sinsentido, pero tiene que ver con la forma que esperamos que adopten las teorías físicas más básicas. ¿Se ha preguntado alguna vez si el Universo es computable? Hay físicos que ya se lo están preguntando, aunque no hay aún una respuesta definitiva, sino una esperanza: que, efectivamente, lo sea. Y si lo es, la Ultima Realidad Física podría ser un mero proceso informático, aunque de una potencia brutal. Todo algoritmo sería, en realidad, un subalgoritmo dentro de un algoritmo global (¿conoce el sentido en Física de la frase "la vista de Dios"?). Y las entidades "platónicas" como los números complejos, que tanto han atormentado a Roger Penrose, serían el resultado de intentar analizar el funcionamiento de la Máquina mediante técnicas "orientadas a objetos". Algo parecido a los rostros que el ojo humano termina por ver en cualquier nube de verano.
... y no, no he bebido ni fumado nada raro :)

Etiquetas: ,

Para febrero del 2008...

Etiquetas: , ,

jueves, agosto 09, 2007

Nueva versión de Intuitive C#

Hay nueva versión de Intuitive C#. Sigue siendo un libro incompleto, aunque hay 30 páginas más que en la última versión. No he intentado disimular los huecos (sobre todo en el capítulo 2). No sé si voy a tener tiempo para seguir actualizando este libro: más prioridad tienen el nuevo libro (para febrero de 2008) y el curso de ADO.NET (para septiembre).

Etiquetas: ,