[bcn-pm] Curso; dudas(regex, substr vs unpack, subrutinas)

Alejandro Exojo suy a badopi.org
dij abr 11 14:39:44 PDT 2013


El Jueves, 11 de abril de 2013, Sergio González Rodríguez escribió:
> ¡Hola mongers!
> 
> Varias cosas:
> 
> 1) Agradeceros la repetición del curso
> 
> foreach my $persona (@personasQueHicieronPosibleElCurso) {
>     print "Gracias $persona ;)\n";
> };

Este es el primer correo que mando, y decir que también hice el curso, y que 
me ha picado mucho la curiosidad, y estoy pasándomelo bien convirtiendo mi 
blog a Mojolicious. Está siendo una experiencia interesante. :)

Aunque yo lo diría:

say "¡Gracias $_!" foreach @personasQueHicieronPosibleElCurso; # ;-)
 
Voy a intentar responderte para afianzar mis conocimientos, pero no te lo tomes 
nada en serio, porque he escrito unos 3 programas en Perl hasta la fecha. :-)

> 2) Tengo unas cuantas dudas, espero que no sean muy noobs ni rebuscadas y
> os entretengáis echándome un cable, os lo agradeceré:
> 
> 2.1) substr vs unpack
> 
> En el Perl cookbok (cap.1 accessing substrings:
> http://docstore.mik.ua/orelly/perl/cookbook/ch01_02.htm ) dice que podemos
> usar unpack para extraer substrings más rapidamente que con substr.
> 
> Teniendo una $cadena = 'cadena de texto'
> Podemos extraer el 'de' así:
>     substr($cadena, 6, 3);
>     o asi
>     unpack("x7 A2", $cadena);
> 
> He mirado el perldoc de unpack(
> http://perldoc.perl.org/functions/unpack.html ), y otro tutorial(
> http://www.perlmonks.org/?node_id=557655 )
> y no me queda nada claro "de qué va el unpack..." simplemente que es más
> rápido que el substr porque lo dice el cookbook...
> 
> El debate sería: ¿Qué os parece usar el unpack como en este ejemplo frente
> al substr? ¿Lo usáis? ¿Cuando y cuando no?

Yikes! Ni flores, pero por lo que entiendo de la documentación de pack(), 
parece estar más orientado a bytes que a cadenas. Pensar en bytes (i.e. 8 
bits), es un error en estos días en que el texto está muy frecuentemente en 
utf-8. En utf-8 el texto de un sólo carácter puede ocupar 1, 2, o más bytes. 
La Ñ, la Ç, etc., ocuparán 2 bytes, por ejemplo. Si estás pensando en cadenas, 
creo que lo correcto es usar substr.

> 2.2) Llamadas a subrutinas
> marine();
> o
> &marine();
> 
> ¿simple cuestión de estilo o tiene alguna otra implicación?

Por lo que he ido leyendo, el & es innecesario estos días, salvo en 
situaciones que raramente vayamos a ver. Es más, si no me suena mal del Modern 
Perl, puede hacer que se comporte de manera diferente. Conclusión: no lo uses 
salvo que realmente sepas lo que estás haciendo.

> 2.3)Expresiones regulares
> Leyendo de un archivo con líneas que contienen lo siguiente:
> FBtr123;blablabla
> Y
> FBtr123,FBtr567,FBtr120;blabla
> 
> Para almacenar estos match estoy haciendo:
> push(@FBtr, $1) if ($line=~/(FBtr\d+);/ || $line=~/(FBtr\d+,.+);/ )
> #guardar un match si sólo hay uno, y guardarlos todos si sólo
> ¿Es esto lo mejor?
> 
> ¿o seria mejor así?
> push(@FBtr, $1) if ($line=~/(FBtr\d+);||(FBtr\d+,.+);/ )
> 
> *empecé a descubrir algo de los lookahead,  y pensé que podría
> implementarlo para ver si hay 'un solo fbtr'  o 'más de uno' pero creo que
> también eso sería liar el rizo innecesariamente ¿os parece?

En esto sí que no sé que decir porque no estoy seguro de lo que estás buscando 
exactamente. Tampoco ayuda que, al ponerlo todo en una línea, si no sabes 
claramente lo que quería hacer el que lo ha escrito, es difícil. :-)

Aún estoy acostumbrado a usar llaves para marcar todos los bloques 
explícitamente, salvo que sea algo muy sencillo como el foreach del principio 
del correo.

> 2.4) Paso de argumentos a subrutinas
> Pasando por valor, la subrutina se hace una copia interna del argumento,
> así que no podemos devolverlo fuera de la sub (o si lo devolvemos no será
> el modificado dentro de la sub)

Si lo devuelves como valor de retorno de la subrutina, pues quien invoque la 
subrutina tendrá que guardarlo de alguna manera. Pero si dentro lo modificas, 
pues lógicamente la modificación se pierde si no sale afuera de alguna manera.

> Pasando por referencia, la sub puede modificar dichos argumentos.
> Pero, si quisiera pasar un array, aunque no quiera que lo modifique; ¿
> Debería pasarlo referenciado, por que si no hará la ¿expansión?/flatten del
> array ?
> Es decir
> $marine($a, \@b) #Bien?
> &marine($a, @b) #Mal porque expande @b?

En el primer caso la subrutina recibe dos parámetros, y están bien 
diferenciados (el segundo será una referencia seguro, el primero... bueno, 
podría serlo si $a lo es). En el segundo, la subrutina recibe tantos como 
elementos tenga @b más uno adicional, $a.

No creo que sea importante como lo hagas, siempre que @b no tenga una 
barbaridad de datos, ya que al pasarlos por valor, se copian. Si lo haces de 
la segunda manera, es cierto que la subrutina lo ve todo "aplanado" o 
"aplastado" a un solo array @_.

¿Es eso problema? Si tú haces la subrutina y tú la usas, no. Para recuperar 
los valores dentro te basta con hacer:

my $a = shift; # Extraigo un valor de @_, que es el $a de fuera
my @b = @_; # Recupero el resto de valores de @_ de golpe.

Si lo haces de la otra manera, como referencia, tendrás que hacer algo 
parecido:

my ($a, $b) = @_;

Pero ahora para usar $b, tendrás que desreferenciar cada vez, en plan @$b o 
$b->[0], que es feo de narices, y un tostón. :-)

> use 5.010;
> say "un abrazo!! " ;

Argh, odio esto de Perl. :-)

Tener que decir que uses una versión en concreto para poder usar un simple 
say()... Pero en caso de necesitarlo prefiero decir "use feature 'say';". Así 
queda claro que es lo que necesitas.

-- 
Alex (a.k.a. suy) | GPG ID 0x0B8B0BC2
http://barnacity.net/ | http://disperso.net


Més informació sobre la llista de correu Barcelona-pm