En Perl, las llamadas de función se han optimizado para no requerir el sigil &
en todo momento. Cuando se declara una subrutina:
sub hello {print "world\n"}
se le puede llamar como hello;
o hello();
o &hello();
que todos hacen lo mismo.
Si su subrutina toma argumentos, es un poco diferente:
sub hello {print "Hello, @_!\n"}
hello 'World'; # prints 'Hello, World!'
hello('World'); # same
&hello('World'); # same
hello; # prints 'Hello, !'
&hello(); # same
&hello; # different, uses whatever was in @_ when hello was called
@_ = 'Bob';
hello; # prints 'Hello, !'
&hello(); # prints 'Hello, !'
&hello; # prints 'Hello, Bob!'
Así como se puede ver, utilizando el sigilo &
es en gran medida redundante, excepto en el caso en que no hay ninguna lista de argumentos. En ese caso, se llama a la subrutina con los valores actuales en @_
.
El &
sigil también tiene otro comportamiento especial, relacionado con los prototipos de Perl. Digamos que estuviera escribiendo su propia función keys
, y quería que se comporte como Perl:
sub mykeys (\%) {keys %{$_[0]}}
Aquí el Perl (\%)
prototipo dice que el primer argumento de mykeys
debe ser un hash literal (que se pasa como un hash referencia).
my $hashref = {...};
say for mykeys %$hashref;
Si por alguna razón usted necesita para conseguir alrededor de este requisito (por lo general no es la mejor idea), se podría escribir esto:
say for &mykeys($hashref); # note that there is no `%`
En este caso, la adición de &
antes de la sub desactiva el prototipo comprobar y cualquier acción posterior que habría realizado (como tomar la referencia). En este uso, &
es básicamente una afirmación de que sabes exactamente qué argumentos necesita mykeys
, y no quieres que perl se interponga en el camino.
En general, se debe evitar el uso de &
en las subrutinas, a menos que desee explícitamente uno de los comportamientos que mencioné anteriormente.
Por último, &
también se necesita cuando se está refiriendo a la referencia de código real:
my $coderef = \&hello;
o
if (defined &hello) {print "hello is defined\n"} # but is not called
Como otros han mencionado, el operador my
declara las variables en el alcance léxico actual. Se requiere cuando se carga el pragma use strict;
.Perl tiene dos tipos de variables, las variables léxicas declaradas con my
y las variables del paquete.
my
variables viven en lo que se llama una almohadilla léxica, que es un espacio de almacenamiento creado por Perl cada vez que se introduce un nuevo ámbito. Las variables de paquete viven en la tabla de símbolos global.
use strict;
use warnings;
$main::foo = 5; # package variable
{ # scope start
my $foo = 6;
print "$foo, $main::foo\n"; # prints '6, 5';
} # scope end
print "$foo, $main::foo\n"; # syntax error, variable $foo is not declared
Puede utilizar la palabra clave our
para crear un alias de léxico a una variable global:
use strict;
our $foo = 5; # $main::foo == $foo
{ # scope start
my $foo = 6;
print "$foo, $main::foo\n"; # prints '6, 5';
} # scope end
print "$foo, $main::foo\n"; # prints '5, 5'
# since $foo and $main::foo are the same
Para los futuros lectores: La respuesta de Eric Strom es el único que es totalmente correcto. El prototipo de comportamiento de derrota de '&' es importante de saber. – Ashley
Actualizado con una nueva respuesta =) – robobooga