30 octubre 2008

GPicView 0.1.10 en Ubuntu Gutsy

GPicView es un rápido visor de imágenes, bastante más rápido que el que incluye Ubuntu por defecto (eog). El problema es que en Gutsy no viene incluido en los repositorios -o yo no he sabido encontrarlo- y hay que instalarlo a mano.

Nos bajamos pues la última versión des de la web de gpicview, en mi caso la 0.1.10.

Primero hay instalar las dependencias para poder compilarlo:
$ sudo apt-get install libgtk2.0-dev

Y luego seguimos el proceso estándar de configure, make y make install (si faltaran más dependencias, configure nos lo indicaría).
$ tar xvzf gpicview-0.1.10.tar.gz
$ cd gpicview-0.1.10/
$ ./configure
$ make
$ sudo make install

Podemos ejecutarlo des de la consola con:
$ gpicview

También encontraremos un nuevo lanzador de la aplicación en el menú "Aplicaciones" > "Gráficos".

Si queremos configurar gpicview como nuestro visor de imágenes por defecto (con los tipos de imagen que tiene actualmente eog):
$ xdg-mime default gpicview.desktop `grep 'MimeType=' /usr/share/applications/eog.desktop | sed -e 's/.*=//' -e 's/;/ /g'`

¡Y listos!

25 octubre 2008

Una de ruby: cuidadín con ||= (o cómo destruir una central nuclear sin querer)

El operador ||= de ruby, también conocido como operador de asignación condicional (conditional assignment) se suele utilizar para inicializar una variable a un valor por defecto si esta es nil o false.

Una muestra de cómo se puede liar parda si este operador no se usa correctamente:
def modificar_central_nuclear(accion, opciones={})
opciones[:avisar_supervisor] ||= false
opciones[:efectuar_operacion] ||= true
puts opciones[:avisar_supervisor] ? "Se avisa supervisor de #{accion}" : "No se avisa supervisor de #{accion}"
puts opciones[:efectuar_operacion] ? "Se realiza accion #{accion}" : "No se realiza accion #{accion}"
end
  • Esta función realiza una acción en una central nuclear recién inaugurada. Se establece como regla de negocio que siempre que se efectúe una operación, se debe avisar a un supervisor. Si no se realiza no hay que avisarlo (por ejemplo, cuando se hacen pruebas no hay que molestarle). En términos de código esto significa que en el hash opciones, los valores de :avisar_supervisor y :efectuar_operacion tendrán siempre el mismo valor en el momento de llamar a la función.
  • También se indica que, como caso especial, si se llama a esta función sin opciones, hay que efectuar la acción pero no hay que avisar al operador.
Veamos primero este último punto:
>> modificar_central_nuclear(:subir_temperatura_core)
No se avisa supervisor de subir_temperatura_core
Se realiza accion subir_temperatura_core
=> nil
Funciona bien. Ahora veamos el primer punto (suponemos q desde fuera de este código se cumple que se indican siempre las dos opciones y que estas tienen el mismo valor):
>> modificar_central_nuclear(:subir_temperatura_core, {:efectuar_operacion => true, :avisar_supervisor => true})
Se avisa supervisor de subir_temperatura_core
Se realiza accion subir_temperatura_core
=> nil
Perfecto, somos unos cracks! Y ahora hacemos lo mismo pero no queremos bajar la temperatura ni avisar al operador (estamos probando que se crean logs recién introducidos p.ej):
>> modificar_central_nuclear(:subir_temperatura_core, {:efectuar_operacion => false, :avisar_supervisor => false})
No se avisa supervisor de subir_temperatura_core
Se realiza accion subir_temperatura_core
=> nil
Ostras!! Parda habemus liada! Hemos subido la temperatura del core y encima sin avisar al supervisor... Evidentemente lo que esperábamos era que no se subiera la temperatura y que no se avisara al supervisor...

Veamos por qué pasa esto:
x ||= 'valor por defecto'
La sentencia anterior asignará el valor 'valor por defecto' a la variable x si:
  1. La variable no existe (la crea y le asigna 'valor por defecto')
  2. La variable existe y su valor anterior es nil
  3. La variable existe y su valor anterior es false
El tercer punto es el motivo por el cual "falla" el uso que hacemos de ||= con booleanos. Nosotros inicializamos opciones[:efectuar_operacion] con el valor false antes de ejecutar la función, pero una vez dentro de esta, el operador condicional por la regla 3 considera que no está inicializada (existe la variable pero su valor anterior es false) y le da el valor a la derecha del ||= (o sea, true).

Resumiendo: nunca de los jamases usar ||= con booleanos, especialmente si el valor anterior puede ser false. En el caso que nos ocupa es preferible hacer esto:
opciones[:efectuar_operacion] = true if opciones[:efectuar_operacion].nil?
El código final quedaría:

def modificar_central_nuclear(accion, opciones={})
opciones[:avisar_supervisor] = false if opciones[:avisar_supervisor].nil?
opciones[:efectuar_operacion] = true if opciones[:efectuar_operacion].nil?
puts opciones[:avisar_supervisor] ? "Se avisa supervisor de #{accion}" : "No se avisa supervisor de #{accion}"
puts opciones[:efectuar_operacion] ? "Se realiza accion #{accion}" : "No se realiza accion #{accion}"
end
Y ahora sí que obtenemos el resultado esperado:

>>modificar_central_nuclear(:subir_temperatura_core, {:efectuar_operacion => false, :avisar_supervisor => false})
No se avisa supervisor de subir_temperatura_core
No se realiza accion subir_temperatura_core
=> nil