Aprendiendo Perl, el reto: Encontrar duplicados

Javier Tiá javier.tia en gmail.com
Jue Abr 5 19:13:56 PDT 2012


Hola nuevamente,

2012/4/4 Marcelo <marcelo.magallon en gmail.com>:
> ¡Hola!
>
> 2012/4/3 Javier Tiá <javier.tia en gmail.com>:
>
>> sub get_hash($)
>
> Esta es una mala costumbre mía que me ha costado mucho soltar.  Los
> prototipos para las subrutinas en Perl pueden ser contraproducentes.
> En este caso el efecto del prototipo es que Perl reclama si uno no
> llama a la subrutina con exactamente un argumento, y es la razón por
> la que a mi me cuesta deshacerme de esa costumbre.

Me parece, es una mala costumbre de muchos por la falta de claridad en
el uso de los prototipos en Perl.

> Sin embargo en este caso:
>
> sub magia(\@\@)
>
> tiene un efecto inesperado.  Si uno invoca a esta función así:
>
> magia(@a, @b);
>
> cualquier desarrollador de Perl viendo esa línea simplemente asumirá
> que @a y @b se van a "juntar" en un solo gran array en @_ dentro de la
> subrutina, pero por el prototipo lo que Perl realmente hace es pasar
> los dos arrays como referencias.  Uno puede argumentar que eso es
> bueno porque es exactamente lo que quien escribió el código espera que
> suceda, pero no es evidente para quien está leyendo el código.  Esto
> en cambio es claro:
>
> magia(\@a, \@b);
>
> Hay otra razón para no usar prototipos: no hacen lo que la mayoría
> queremos que hagan.  Lo que un prototipo realmente hace es imponer
> contexto, no requerir una cantidad particular de argumentos como
> señalé antes.  Intuitivamente uno espera que Perl reclame con este
> programa:
>
> #!/usr/bin/env perl
>
> use Modern::Perl;
>
> sub n($)
> {
>    my $arg = shift;
>    say $arg;
> }
>
> my $a = 1;
> my @b = (0, 0, 0);
>
> n($a);
> n(@b);
>
> pero no, este programa no solo corre sin objecciones sino que hace
> exactamente lo dice ahí que tiene que hacer.  Si reclama en este caso
> por ejemplo:
>
> n($a, @b);
>
> y reclama exactamente en la forma que uno quiere que reclame:
>
> Too many arguments for main::n at [...], near "@b)"
>
> por eso cuesta tanto abandonarlos.
>
>> {
>>    open(FILE, $_);
>>    return Digest::MD5->new->addfile(*FILE)->hexdigest;
>> }
>
> En general uno no debería usar otra cosa que no sea la forma de tres
> argumentos de open, así:
>
> open(FILE, "<", $_)
>
> Otra vez: esto hace explícito que es lo que uno pretende.
>
> La otra cosa es que uno no debería usar "palabras chingas" (barewords)
> como "FILE".  En el caso de este código en particular, lo que está
> sucediendo es que se abre el archivo, se lee y se deja abierto hasta
> la siguiente llamada de esa función.  Hasta ese momento se cierra el
> archivo porque Perl ocupa el filehandle (FILE).  Se abre el siguiente
> archivo y queda abierto hasta la siguiente vez que se llame esa
> función.  Esto sucede porque el "scope" de *FILE es el paquete, no la
> función.  Y el problema con los barewords es exactamente ese.

Buen consejo, anotado para hacer mejor uso de 'open' en las próximas
líneas de Perl.

> Y una cosa que tal vez es menos cosmética es el uso de $_.  $_ *no* es
> el argumento de la función.
>
> Si uno va a:
>
>   $hashes{$File::Find::name} = get_hash($_) if -f $_;
>
> y cambia "get_hash($_)" por "get_hash('el cielo pintado de azul')" se
> ve que el código funciona exactamente igual.  En la función $_ sigue
> siendo la misma variable que en el entorno donde fue llamada.  No solo
> tiene el mismo valor, es la misma variable.

Esta parte me resulta confusa.
Puedo usar "get_hash('el cielo pintado de azul')" o "get_hash($foo)"
que esperaría el mismo resultado, pero si uso "get_hash" o
"get_hash()" me da error.
Si no importa tanto el parámetro dentro de la subrutina, ¿Por qué
obligatoriamente tengo que pasarle 'algo', con cierta tendencia a
'cualquier cosa', como parámetro dentro una subrutina?

Espero esa sea la pregunta correcta :)

> Este programa puede resultar sorpresivo:
>
> #!/usr/bin/env perl
>
> use Modern::Perl;
>
> sub n { $_ = 2; }
>
> $_ = 1;
> n;
> say;

Este ejemplo me gustó, me llevó a estudiarme un poco más el
alcance(scope) de las variables y la influencia en ellas de las
órdenes internas('my' y 'local').

Gracias y saludos,

-- 
Javier Tiá


Más información sobre la lista de distribución Costarica-pm