[Perl] equivalencia de un case
Salvador Ortiz Garcia
sog@msg.com.mx
13 Mar 2002 00:00:05 -0600
On Tue, 2002-03-12 at 16:00, Gunnar Wolf wrote:
> > > Voy a implementar en una programacion que tengo operativa en PERL un =
modulo de traduccion por llamarlo de alguna forma.
> > >
> > > Se trata de hacer algo como el sistema que utiliza el php-nuke
> > >
> > > Pero PERL no tiene ninguna sentencia equivalente.
> >(...)
> > Ahora que, a mi me gusta m=E1s usando un hash:
> >
> > my %Maps =3D (
> > '0001' =3D> 'Mensaje n=FAmero uno',
> > '0002' =3D> 'Mensaje n=FAmero dos',
> > # Etc;
> > };
>=20
> A m=ED me gusta abundar un poco en esto, si vas a pasar seguido por esta
> construcci=F3n:
> %tipo =3D ( 'a' =3D> sub { print "Es de tipo A\n"; },
> 'b' =3D> sub { print "No, no me gusta...\n"; },
> 'c' =3D> sub { otraCosa(1,2); } );
>=20
> Y cuando lo requieras, la llamas as=ED:
>=20
> &{$tipo{$expr}};
Pues abundemos ;-)
Primero, ya s=E9 que adoras el &, pero creo que es m=E1s claro si usas:
$tipo{$expr}->()
Dos, y m=E1s importante, los "closures" son herramientas poderosas, pero
hay que tener cautela al usarlos:
Si lo que quieres es una tabla de mapeo es mucho m=E1s eficiente y m=E1s
claro hacerla directa como la que puse primero.
Si lo que quieres en un "despachador de funciones", es mejor en t=E9rminos
de eficiencia, y se usa igual, hacer un hash de referencias simples a
funciones, aunque escribas m=E1s:
sub func1 { ... }
sub func2 { ... }
...
%dispatch =3D ( 'a' =3D> \&func1, 'b' =3D> \&func2, ... );
$dispatch{$selector}->(...);
O incluso puedes hacer algunos jueguitos con namespaces:
sub MyDisp::a { ... }
sub MyDisp::b { ... }
"MyDisp::$selector"->(...); # Sog's style
&{"MyDisp::$selector"}(...) ; # Gunnar's style
Pero crear N closures, que te capturan, cada uno, todo el =E1mbito l=E9xico
de tu programa sin una necesidad real lo considero excesivo.
Si no queda claro a qu=E9 me refiero, hagsmos un "factory" de contadores,
ejemplo en que los closures son la mejor opci=F3n, pero en que tengo el
=E1mbito l=E9xico controlado y lo necesito:
# Ejemplo Verboso por claridad
sub ContFactory {
my $Base =3D shift; # Desde donde cuento
my $Incremento =3D shift || 1; # De cuantos en cuantos
my $func =3D sub { # Construyo un closure, en cuyo =E1mbit=
o
my $current =3D $Base; # tengo atrapados $Base e $incremento
$Base +=3D $Incremento;
return $current;
};
return $func; # Lo devuelvo
}
# Construyo un contador1, desde 0, con incr de 10=20
$cont1 =3D ContFactory(0,10);
# Ahora otro, desde 15 con incr de 3
$cont2 =3D ContFactory(15,3);
# Los llamo uso unas cuantas veces
for(0..10) {
print $cont1->()," ",$cont2->()," ";
}
Pregunta capsiosa: "Cual es el valor de $Base ahora?"
Respuesta posible: "Cu=E1l $Base?, la atrapada en $cont1 o la en $cont2?"
Ahora si, cada uno de los contadores carga con su _propia_ instancia de
las variables l=E9xicas existentes en el =E1mbito en que el closure fu=E9
creado y te garantiza un encapsulamiento total, pues no existe forma de
que desde "afuera" se alteren, pues cuando ContFactory regres=F3
desaparecieron de cualquier =E1mbito externo.
Por supuesto que eso tiene sus costos y en un descuido acabas teniendo N
instancias inutiles de un mont=F3n de variables.
Saludos.
Salvador Ortiz.