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