2011-02-17 11 views
8

Puedo saber de qué sirve el & en frente de los subs cuando, sin él, los subs todavía se pueden ejecutar.Sintaxis de Perl sigil

Y también, el my delante de las variables perl.

Sé que es para la sintaxis del lenguaje estricto o no, pero ¿por qué no simplemente lo convierten en un estándar que cada variable debe ser declarada por un my?

EDIT

Gracias por todas sus discusiones/respuestas, que desean aceptar muchas de sus respuestas, pero ya que soy sólo puede aceptar una, me aceptarán aquel en el que otros usuarios puedan entender con facilitar.

+1

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

+0

Actualizado con una nueva respuesta =) – robobooga

Respuesta

12

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 
+0

Gracias por su respuesta y explicaciones muy completas – robobooga

+0

@Eric Strom: Usted dice que & generalmente no debe utilizarse. Sin embargo, he notado que emacs hace un resaltado de sintaxis agradable si usas & sub para llamadas de subrutina. ¿Existe un inconveniente o peligro específico de usarlos para este propósito? O, preferiblemente, ¿hay alguna manera de obtener emacs para sintaxis resaltar subs sin él? – yarian

+0

@YGomez => el peligro de usar '&' todo el tiempo es que '& mysub' y' & mysub() 'hacen cosas MUY diferentes (el primero llama al sub con el valor actual de' @ _', y el último llama el sub con una lista de argumentos vacía). Dado que los dos nombres son visualmente similares, puede ser fácil confundir uno con el otro, lo que dará lugar a errores difíciles de diagnosticar. Dado que Perl no requiere el 'y' en la mayoría de los lugares, es mejor dejarlo fuera, y solo usarlo cuando explícitamente desea el comportamiento que puede proporcionar. En lo que respecta a emacs, estoy seguro de que hay otro modo de resaltado de sintaxis. –

8

El my limita la variable al alcance actual. Con el use strict pragma, que debe usar, debe declarar las variables (por ejemplo, con my). La alternativa de irse sin existe por razones de flexibilidad para scripts muy cortos.

& casi nunca se utiliza, ya que Perl interpreta por defecto las palabras sigil-less como subrutinas, pero es útil si desea crear una referencia a la subrutina.

sub say_hi { print "hi\n" } 
my $sub_ref = \&say_hi; 
+1

respuesta simple y directa .. Gracias por aclarar =) – robobooga

5

se puede saber cuál es el uso de la & frente a los submarinos cuando sin ella, los sandwiches son todavía capaces de correr.

compatibilidad hacia atrás con Perl 4

Y también, el de mi frente a las variables de Perl.

Establece ámbito de bloque

Sé que es para la sintaxis del lenguaje estricta o lo que no, pero ¿por qué no simplemente lo convierten en un estándar que todas las variables debe ser declarada por un mi?

  1. Compatibilidad hacia atrás (de ahí use strict; rechazando las declaraciones de variables desnudos)
  2. Las variables también se pueden declarar con our o local
+2

también es más fácil escribir 1 líneas con 'perl -e' sin' mi'. – xenoterracide

0

& ha sigue siendo bastante bueno distinción: llamar con ella (&YourSub) hace actual @_ visible para sub llamado también. De todos modos, lo uso en mis scripts sobre todo por razones de claridad: deja en claro, que son mis propias funciones y las funciones de núcleo o módulos.

Acerca de my. Todos los tutoriales y documentos sugieren utilizar use strict; pragma, por lo que debe declarar su varaible con my también.Entonces, la situación desde mi punto de vista es bastante atrás: si el alcance es tan importante para las mejores prácticas, sería normal que las variables tengan un alcance predeterminado (como decimos con my ahora) y cuando realmente necesitamos variables globales, deberíamos declararlos como eso. Entiendo que es el legado de Perl, pero aún así es contrario a la ideología de Perl evitar la redundancia. El uso de my cada vez que se declara podría ser anulado por algún tipo de pragma. [Lo siento, robobooga, tal vez ir demasiado lejos de tu pregunta]

+2

Desafortunadamente, si, por ejemplo, Perl 5.14 habilitaría 'strict' por defecto, entonces todo el código de Perl existente que * no *' use strict' se rompe instantáneamente. Perl 5.12 va un poco en esta dirección: si 'usas 5.012', entonces' strict' se activa automágicamente. – mscha

+0

@mscha: sí, entiendo, no hay manera de hacer un estricto pragma predeterminado para cada script escrito allí, pero sueño con pragma, donde todas las variables son por defecto locales en su alcance y cuando necesito variables globales, declararlos explícitamente con 'our' –

+2

En realidad, no me importa usar' my' tan a menudo. Cuando tengo una variable en el alcance más externo y también declaro una función con una variable del mismo nombre (para mayor claridad, a su manera) sé que estoy obteniendo una nueva variable en el sub, porque ahora tengo que pensar que NO usar mi en lugar de pensar en usarlo. –

4

Si quieres saber cómo escribir Perl moderno, te recomiendo que leas Modern Perl? Puede comprar una versión de árbol muerto o descargar una versión electrónica de forma gratuita.

+0

Parece una buena lectura. Voy a intentarlo ... Esta pregunta es más una cosa que me molesta ya que vi muchos sitios web diferentes con diferentes implementaciones. Probablemente es mi culpa no leer las fechas de publicación. – robobooga