Piedras preciosas de Ruby

19
Julio
2006

Muchas veces en programación hay que tabular una serie de datos. Lo más usual es recorrer toda la serie y contar cada elemento en una tabla.

En Java (1.5) un método de hacerlo sería así:

ArrayList<String> lista = /* una lista de palabras, por ejemplo */;
Hashmap<String, Integer> tabla = new Hashmap();
for (String palabra: lista) {
    int contador;
    if ((contador = tabla.get(palabra)) != null) {
        // La palabra ya estaba en la tabla
        tabla.put(palabra, ++contador);
    } else { // La palabra no estaba en la tabla
        tabla.put(palabra, 0);
    }
}

Es muy simple y muy sencillo gracias principalmente a la posibilidad del bucle for each que nos permite Java 1.5 (a pesar de que tenemos que utilizar templates, que hace un poco pesado escribir las declaraciones iniciales).

En Ruby el anterior código sería similar:

lista = # una lista de palabras, por ejemplo
tabla = {}
for palabra in lista do
  if (tabla[palabra])
    # La palabra ya estaba en la tabla
    tabla[palabra] += 1
   else # La palabra no estaba en la tabla
    tabla[palabra] = 0
  end
end

Se podría decir que Ruby es más expresivo y que Java más académico (cada uno tiene sus opiniones) y en realidad sólo hemos conseguido reducir una línea. Pero el problema del último código es que no utiliza todas las posibilidades de Ruby. Veamos otra posibilidad que utiliza algunos detalles muy interesantes de Ruby.

lista = # una lista de palabras, por ejemplo
tabla = Hash.new(0)
lista.each { |palabra| tabla[palabra] += 1 }

Eso sí que es reducir. Pero el que hace la magia aquí yo creo que es el método constructor de la segunda línea. El parámetro que le pasamos al constructor hace que el elemento por defecto que se devuelve cuando se pide el valor de una clave no existente en el hash sea 0 en vez de nil (en el primer ejemplo se utiliza la propiedad de que nil en las comparaciones booleanas se interpreta como falso). Eso permite que la comprobación por si la clave existe y la inicialización a 0 sean innecesarias.

Una gran idea, sin duda, que hace que ese trozo de código que habremos programado 101 veces pierda un if y gane en simplicidad. Para obtener un funcionamiento similar en Java deberíamos programar una subclase de Hashmap ¿Para cuándo un método setDefault(Object value) en la interfaz Map de Java (interfaz que todos los hashes implementan)?

Visto en la página 18 del libro Programming Ruby, The Pragmatic Programmers’ Guide, Second Edition de Dave Thomas con Chad Fowler y Andy Hunt.


Deja un comentario

Puedes enterarte de las respuestas a tus comentarios de esta entrada mediante myComments.

XHTML: Puedes utilizar las siguientes etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Tu servidor sin límites: 20GB de espacio, 1TB de transferencia, 1 dominio gratuito. Por 1.5€ al mes utilizando el código "RUIDOBLANCO" en DreamHost. Más información.