Un poco de Teoría de la Computación (parte 2)

21 de octubre de 2009

Buen día a todos, bueno continuamos con la divulgación de algunos conceptos computacionales interesantes, ahora con respecto a cómo trabajan los compiladores para entender nuestro código: las estrategias de evaluación de código y la transparencia referencial de las funciones.

Estrategias de Evaluación


En ciencias de la computación, una estrategia de evaluación es un conjunto de reglas que determinarán el valor de cualquier expresión, dentro de algún lenguaje de programación. Se dividen principalmente en dos grupos: Estrictos (strict evaluation) y No estrictos (lazy evaluation).

A ver, veamos un ejemplo sencillo, imaginemos que tenemos la función:

funcion retornaCinco( parametro_opcional )
retornar  5
fin_funcion

¿Cuál sería el resultado si lo llamamos así?

retornaCinco()  -- 5, obvio
retornaCinco(1 / 0) -- 5, en realidad, siempre será 5, no?

Pues resulta que depende, porque en el segundo caso, si el lenguaje de turno es estricto, evaluará la expresión1/0 antes de pasarla como parámetro, así que ocurrirá un error de división por cero, que seguramente detendrá nuestra aplicación.

Aquí la diferencia con un lenguaje no estricto, el cual sólo evalúa el valor de la expresión si es que ésta es utilizada dentro de la función.

Sin embargo, en realidad vamos a encontrar que los lenguajes de la actualidad combinan ambas estrategias de manera peculiar. Por ejemplo, los lenguajes estrictos como C# o Java, tienden a utilizar algún tipo de evaluación no-estricta cuando evalúan bloques IF o Booleanos.

Transparencia Referencial


Dentro de algún programa de computadora, se dice que una expresión es referencialmente transparente si ésta puede ser reemplazada por su valor, sin cambiar el resultado del programa. Por definición, este tipo de expresiones son determinísticas.

Por ejemplo, en las matemáticas, todas las funciones son referencialmente transparentes, ante un mismo parámetro devuelven el mismo resultado, veamos:

Raiz_Cuadrada(4) = 2 -- porque 2 * 2 = 4
Raiz_Cuadrada(4) = 2 -- porque 2 * 2 = 4
Raiz_Cuadrada(4) = 2 -- porque 2 * 2 = 4

Sin embargo, en los programas de computadora, no es lo mismo:

Numero_Dia_Hoy() = 2 -- porque HOY es viernes 2 de octubre
Numero_Dia_Hoy() = 3 -- porque HOY es sábado 3 de octubre
Numero_Dia_Hoy() = 4 -- porque HOY es domingo 4 de octubre…

Vemos que varía, porque la función utiliza una variable libre (el tiempo) que es tomada del entorno o contexto. (ver artículo acerca de las variables libres).

Esto tema es muy importante para conocer y predecir el comportamiento de un programa, lo cual ayuda a los compiladores a tratar de corregir los programas, simplificar los algoritmos, poder modificar el código sin pausar su ejecución, o realizar optimizaciones como la memorización, la eliminación de subexpresiones, o la paralelización de la ejecución del código (ver artículo anterior).

Un ejemplo puede ilustrar estos conceptos, supongamos que tenemos el siguiente código:

X = Raiz_Cuadrada(4) – 4 + (Raiz_Cuadrada(4) * Raiz_Cuadrada(4))

El compilador podría realizar el cálculo de la primera raíz cuadrada de 4, para luego implementar la siguiente optimización, reemplazando la función por su valor:

X = 2 – 4 + (2 * 2)
X = 2 
                   

Con lo cual tenemos un código que se ejecutará más rápido. Sin embargo, si tenemos:

X = Numero_Dia_Hoy() – 4 + (Numero_Dia_Hoy() * Numero_Dia_Hoy() )

Calculando la primera llamada a Numero_Dia_Hoy() tenemos 2 (para el 2 de octubre, ciertamente) pero, ¿podríamos reemplazarlo en las subsiguientes llamadas? Quizás a veces sea correcto, pero ¿qué pasa si lo estamos ejecutando a las 12 pm? podría tener luego el valor de 3 en el milisegundo siguiente. Con esto se haceimposible efectuar la optimización por reemplazo. Aquí estamos ante una función no determinística, ya que no podemos asegurar que su valor siempre será 2.

La transparencia referencial asegura la no existencia de efectos paralelos, y son la base fundamental para la programación funcional (ver artículo anterior). Este tipo de funciones también son conocidas con el nombre de funciones puras (e impuras las que no lo son, consecuentemente).
Lenguajes como Haskell son totalmente puros. OCaml y F# combinan ambos tipos de funciones.

Aplicación práctica


Si venimos desarrollando con algún lenguaje en particular, es importante saber qué tipo de evaluación y optimización está realizando el compilador del mismo, para ayudarle a generar un código más eficiente y contar con aplicaciones más rápidas y robustas.

Muchas gracias por tu lectura, nos vemos en el siguiente post 

Dan Pink en la sorprendente ciencia de la motivacion

28 de septiembre de 2009

En esta conversación para TED, el analista laboral Dan Pink nos habla de la ciencia de la motivación y el nuevo modelo para incentivar a los trabajadores en las empresas, empezando con un hecho que los sociólogos conocen pero no así la mayoría de los gerentes: Los métodos tradicionales de recompensas no siempre son tan efectivos como pensamos, poniendo en la balanza el modelo Recompensa y Castigo versus el nuevo modelo propuesto para el siglo XXI: Autonomía, Maestría y Propósito.


Expone que, en resumen:


1.       Existe una discordancia entre lo que la ciencia dice y las empresas hacen (en lo que a motivación se refiere).
2.       Las recompensas del siglo XX, esos motivadores que creemos son parte natural de los negocios funcionan pero sólo en una sorprendente y estrecha franja de circunstancias.
3.       Las recompensas condicionadas a menudo destruyen la creatividad.
4.       El secreto del alto desempeño no está en imponer recompensas y castigos, sino en una fuerza intrínseca invisible, la fuerza de hacer las cosas por propio interés, la fuerza de hacer las cosas porque importan, porque te hacen sentirte importante, y que formas parte de algo mayor que ti.



Este tema tendrá un impacto profundo en el mejoramiento del ambiente laboral y desempeño, puntos que están a la orden del día en todas las medianas y grandes empresas.

Un poco de Teoría de la Computación (parte 1)

25 de septiembre de 2009

Hola a todos! la motivación del presente artículo nace de la necesidad de comprender algunos temas relacionados con las teoría de la computación, antes de asimilar los nuevos lenguajes multiparadigma, como es el caso de F#, Scala y otros, que se perfilan como herramientas para el futuro del desarrollo de software comercial y empresarial.

Atención! para comprender estos temas sólo requerimos haber programado alguna vez en algún lenguaje de programación, y entender la estructura y funcionamiento general de un programa.

Sus comentarios y aportes serán bienvenidos! Pues bien, en esta ocasión empezaremos con dos conceptos simples: objetos de primera y segunda clase, y variables libres y vinculadas.




Objetos de primera y segunda clase



En las ciencias de la computación, en el contexto de cualquier lenguaje de programación, un objeto de primera clase es una entidad que puede:

  • Ser parámetro de alguna subrutina.
  • Ser el resultado de alguna subrutina.
  • Ser asignado a una variable.


Por ejemplo, en el contexto de Visual Basic, diríamos que los objetos de primera clase son los datos básicos tales como los Enteros, Decimales, Cadenas, y los Objetos (estructuras de datos y subrutinas).

Los objetos de primera clase requieren también que se puedan:

  • Construir en tiempo de ejecución. Ejemplo:

// codigo en javascript
var s = "Hola";
var saludo = new String(s + " " + s + "!");

Aquí es claro que estamos construyendo una secuencia de caracteres con el valor “Hola Hola!”, la estamos grabando en la memoria, y la estamos etiquetando con el nombre de “saludo” (variable de tipo cadena). Otro ejemplo de construcción:

' codigo en Visual Basic
Set Jefe = CreateObject("MiClase.Empleado")
Set Asistente = CreateObject("MiClase.Empleado")

  • Expresarse como valores anónimos (o literales).

Un valor anónimo es aquel que no está etiquetado (asignado) con algún nombre o descripción en particular. Por ejemplo:

// codigo en C#
MessageBox.Show( "No me gusta programar" );
# codigo en Ruby, imprime 12
puts "Cadena Larga".length



En ambos casos hemos construido el valor directamente, sin ninguna variable de por medio, por eso se les conoce como “anónimos”.
De otro lado, en C y C++ por ejemplo, no es posible crear nuevas funciones en tiempo de ejecución. Como resultado, las funciones no son Objetos de Primera Clase, sino que son indirectamente manipulados a través de los muy "temidos" punteros a funciones (o como los delegados en C#). También se les conoce como objetos de segunda clase.




Variables Libres y Vinculadas



Veamos, en las ciencias de la computación, una variable libre es aquella que, en el contexto de una rutina o función, no es local, ni tampoco se obtiene como argumento de la misma. Mmm a ver expliquemos algo más. ¿Qué tipo de variable podría ser esta? Veamos un ejemplo:


     Public Function PromedioSimple( ByVal X as Integer, ByVal Y as Integer )
         Dim Z as Integer
         Z = 2
         PromedioSimple = (X + Y ) / Z
     End Function


Aquí vemos claramente que ni X, ni Y (argumentos de la función), ni Z (variable local) son variables libres. Podríamos hacer que Z sea libre si lo cambiamos así:


     Global Z As Integer
     Z = 2



     Public Function PromedioSimple( ByVal X as Integer, ByVal Y as Integer )
         PromedioSimple = (X + Y ) / Z
     End Function


Ciertamente Z es libre en este contexto, toma independientemente cualquier valor previo a la ejecución de la función. Al resto de las variables (X & Y) se les conoce como variables vinculadas.

Tomemos otro ejemplo del lenguaje cotidiano, analicemos la oración:

     Jorge encontró su libro

Esta oración puede significar dos cosas:

a)   Jorge encontró su propio libro que andaba buscando de hace rato, ó
b)   Jorge encontró el libro de alguien más.

Debido a esto, se dice que el pronombre su es una variable libre, ya puede tomar cualquiera de los dos significados sin problemas.


Siguientes pasos


En un siguiente post hablaremos acerca de la transparencia referencial y los efectos paralelos en un lenguaje de programación, asi como las funciones puras e impuras, conceptos que serán fundamentales en el contexto de la programación funcional.

Gracias por su atención!

Cómo empezar con F#?

18 de septiembre de 2009

Hola a todos! En esta ocasión vamos a dejarlos con un mini-tutorial para que puedan escribir sus primeros scripts con la versión beta de F#, el nuevo lenguaje multiparadigma (imperativo, objetos y funcional) que saldrá en la versión de Visual Studio .NET 2010 y el .NET Framework 4.0, pero con el cual ya podemos ir practicando un poco. Demostraremos como ejecutar nuestra primera aplicación, paso a paso, desde cero.

¿Qué necesitamos?


Para los usuarios que ya tienen instalado Visual Studio versión 2008, pueden descargar la actualización en:

Para los que no lo tienen instalado, pueden descargar Visual Studio Beta 2010 (que incluye F#) en:

La instalación es del tipo next next next así que no creo que tengan muchos problemas aquí.

Pasos a seguir


1. Una vez instalado, abrir el visual studio, clic en File > New > Project, para que aparezca la siguiente ventana:


Imagen1

Le damos un nombre a la solución, en mi caso es Tutorial0. La localización que elegí es C:\Aplicaciones, pero puede ser cualquiera. Al darle clic en OK nos quedara así:


Imagen2


2. Perfecto! ahora lo siguiente es activar el FSI (F Sharp Interactive) que es una ventana de depuración adicional que cumplirá dos funciones fundamentales:
     a. Mostrar el resultado de las comandos de F# que vayamos escribiendo (parecido al Inmediate Window), y
     b. Mostrar los tipos de datos que se usan en dicho comando.

Este ultimo punto cumple un rol didáctico importante ya que, como les comenté en el articulo anterior, F# maneja nuevos tipos de datos que son muy, muy "diferentes" (al menos a todo lo que había visto hasta ahora, personalmente).

Sigamos, clic en View > Other Windows > F# Interactive, o simplemente Ctrl+Alt+F

La ventana nos queda asi:


Imagen3


3. Pues bien, ahora sí estamos listos para ingresar nuestras primeras lineas de código!!! empezaremos dandole el honor al que ya es todo un clásico, el popular HOLA MUNDO que no podía faltar en nuestro tutorial.

Para poder visualizar el resultado de cada linea de manera independiente, sombrear la linea y luego hacer clic derecho > Send to Interactive para ver el resultado en la ventana FSI, tal como muestra la imagen:

System.Console.WriteLine "Hola Mundo!"
printfn "Hola Mundo!"


Imagen4


Cosas para notar:

La primera linea es la forma estándar de C# de enviar una cadena de caracteres al "stream" por defecto, que en este caso es la ventana del FSI (o la pantalla de la PC, cuando ejecutamos la aplicación).
La segunda es la forma estándar para el lenguaje F#

Y bueno qué rayos significa val it : unit = ( ) ??? pues es la descripción del modelo o patrón que está utilizandose en esta sentencia de F# en particular... mmm osea es como una descripción de los tipos de datos que intervienen, y la relación que tienen. Sí, lo mismo pienso... pero espero darles mejores explicaciones pronto...


4. Para evitarnos problemas con futuros ejemplos mi consejo es que agreguen las referencias a las siguientes librerias (clic en Project > Add Reference)

System.Windows.Forms
System.Net

Asimismo, importar las librerías base al inicio de nuestras aplicaciones en F#:


open System
open System.IO
open System.Net

Imagen5



con lo que nuestro HOLA MUNDO se vería así:


open System
open System.IO
open System.Net





Console.WriteLine "Hola Mundo!"
printfn "Hola Mundo!"




Para terminar


¿Qué creen que pasará cuando ejecuten las siguientes líneas?


let f = new System.Windows.Forms.Form(Visible=true, Text = "Hola Mundo!")
f.Text <- "No Me Gusta Programar"
f.Click.Add( fun _ -> printfn "Click!" )




Oh! este código me trae algo de nostalgia, puesto la sentencia LET es la primera que aprendí a utilizar cuando me enseñaron lenguaje BASIC, hace muuuchos años :_( ... en ese entonces también servía para asignar valores a variables, algo así como en LET X = 10

Weno ya dejándonos de cosas... pues prueben ustedes mismos a ver qué pasa (pueden adjuntar sus resultados).

Pues bien gracias por seguirnos hasta aquí, y plsss por favor espero sus comentarios!

Saludos a todos.