La vida moderna de edgar

Tags:
< September 2006 >
SuMoTuWeThFrSa
      1 2
3 4 5 6 7 8 9
10111213141516
17181920212223
24252627282930

Un mal día, mi jefe llegó preguntando por un forma de analizar unos logs de un programa que utilizamos. Primero una cosa sencilla, y mi tonta cabeza pensó:

Procesamiento de texto + Algoritmo simple = Perl

No lo vuelvo a hacer.

En ese momento pareció y fue buena idea, detectar un patrón de texto en un archivo, organizar un poco el texto y limpiarlo, parecía y fue factible, cuestión de minutos, más tiempo en recordar Perl, afinar la expresión regular, ver unos cuantos ejemplos sobre arreglos (pero se veía que llegaba a cosas oscuras) y listo.

Luego al ver el resultado y que había áreas de oportunidad, el requerimiento creció considerablemente; se encontró un error y seguimos para adelante.

El error fue resuelto, no sin sus problemas. En mi cabeza rondaban distintas formas de resolverlo, alguien con idea en el problema del análisis de texto podrá recordar estos problemas alguna vez:

Teoricamente el archivo tiene la forma:

 [Una linea]
 [Una linea]
 ...

Pero en realidad tenía la forma:

 [Una linea]
 [Una linea][Una linea]
 [Una linea][Una mentirosa linea][Una linea]
 [Una
 linea]
 [Una
 linea][Una linea]
 ...

Y combinaciones peores que esa. Así que como opciones encontré:

  • Considerar que el salto de linea no fuera mi separador de cadenas.
  • Que mis expresiones regulares fueran multi-lineas.
  • Otro par que afortunadamente ya no recuerdo.

Al final, después de pensarle un poco dí con una solución correcta. Pero recae muy poco en el poder de Perl de manejar expresiones regulares, tanto que podría haberlo escrito en Python sin ningún contratiempo, al menos no hubiera sido peor que lo que había hecho en Perl.

Pero hasta ese momento puedo presumir de que Perl había realizado su tarea sin muchos problemas. El problema fue cuando quise implementar los requerimientos extras.

En cuanto a mis requisitos para el lenguaje, una vez diseñada mi solución (y que decidí limpiar un poco el código) son:

  • Arreglos de Hash.
  • Arreglos de Arreglos de Hash.
  • Funciones que reciben valores por referencia.
  • Referencia a elementos de arreglos o de Hash.

Estas cosas suenan de lo más natural e inocencentes y han probado ser una desgracia infinita para mí. No por que no pueda resolver mi problema, sino por que no encuentro la forma correcta de hacerlo. Me centraré en el problema de las referencias para ejemplificar. Tengo un archivo de pruebas que voy generando mientras voy aprendiendo gramática nuevas (Sí, mientras voy aprendiendo formas nuevas de hacer lo mismo sigh).

Al inicio del archivo declaro mis buenas intenciones, la prueba es clásica, declaro una variable ($a) luego hago una referencia a ella $b y modifico el valor de la variable via su referencia. No me voy a meter en lo feo que se ve \$, yo creo que esto aceptable en un lenguaje como Perl:

   # Trying to learn how to use references in perl

   # Lesson 1: Make reference with \$ and dereference with $$
   $a = "pp";
   $b = \$a;
   $$b = "qq";
   print "\$a changed via \$\$b $a\n";

Después intento hacer lo mismo via referencias, tomo la referencia de $a via \$a sin variables intermedias, está todo bien, cuando declaro la variable con my, no pongo $$, sólo en el resto de los casos. Esto es coherente, puedo pasar de mi lección 1 a la lección 2 sin problemas:

   # Lesson 2: This works for functions too in the same way \$ and $$
   sub t {
       my $p = shift;
       $$p = "rr";
   }

   t(\$a);
   print "\$a changed via t(\\\$a) $a\n";

Por alguna extraña razón en mi script de trabajo, necesito utilizar prototipos (que por cierto no pudieron ser más feos) así que me pongo a probar como hacer prototipos. Y aquí es donde surge la duda, ¿qué recibe la función? Siendo coherente con la lección 2, una referencia a escalar (\$), no un escalar realmente, pero aparentemente las referencias a escalaras son... escalares. Así que yo no me fuí con el ejemplo anterior y jugué un poco, después de esto obtuve este código funcional:

   # Lesson 3a: with prototypes
   sub u ($);

   u(\$a);

   sub u ($) {
       my $p = shift;
       $$p = "ss";
   }

   print "\$a changed via u(\\\$a) $a, with prototype u(\$)\n";

Poniendo atención a la linea de asignación en la función `$$p = "ss"`. Por que aquí viene el momento en que decimos Bienvenido a Perl:

   # Lesson 3b: same to the one above but using declaring the reference
   # in the function no in the call
   sub v (\$);

   v($a);

   sub v (\$) {
       my $p = shift;
       $$p = "tt";
   }

   print "\$a changed via v(\$a) $a, with prototype v(\\\$)\n";

Veamos, utilizando una referencia ahora sí, entonces, resulta que $p tiene una referencia que con $$p se puede "desreferenciar". Bien entonces si \$a es una referencia y $a es un escalar, ambos enviados a una función, $$p, sirve para acceder al mismo valor en ambos casos? ¿\$a y $a son sinónimos? No, pero me dan el mismo resultado, ¿cómo se supone que debo hacerlo? Buscando esta respuesta se me ocurrió otra combinación:

   # Lesson 3c: same to the others, not declaring reference in the call
   # nor the declaration, just use it via $$
   sub w ($);

   w($a);

   sub w ($) {
        my $p = shift;
        $$p = "tt";
   }

   print "\$a changed via w(\$a) $a, with prototype w(\$)\n";

Aquí es donde nos paramos de la mesa y mejor nos vamos a otra cosa. La función espera un scalar, recibe un scalar, y mágicamente, con la soberana autoridad de hacer lo que se le da la gana "desreferencia" un scalar ¿? Sí. Eso hizo y tengo un nuevo valor para $a.

¿Cuál es la forma correcta de hacerlo?

En este momento me parecía que la última, ya que aunque no era explicita -ni mucho menos- era la menos fea (la \ es horrible). Aunque es la peor en términos de su significado (no dice nada al respecto de que se esta haciendo). Pero cuando intenté extender esto a arreglos me dí cuenta que esa era mi peor opción.

Eso lo pondré en otro episodio más de: No importa cuanto procesamiento de texto te prometan, si un lenguaje programación no es capaz de mantener una sintaxis estable y elegante para estructuras de datos complejas gira la página y vete al siguiente.

Fecha publicación: 28 Sep 2006 21:20 | temas relacionados: | permalink | comentarios (0) | trackback