Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl syntax sigil

Tags:

syntax

perl

May I know what's the use of the & in front of subs when without it, the subs are still able to run.

And also, the my in front of perl variables.

I know it's for strict language syntax or what not, but why don't they just make it a standard that every variable needs to be declared by a my?

EDIT

Thanks for all of your discussions/answers, I wish to accept many of your answers, but since I'm can only accept one, I will accept the one where other users might understand with ease.

like image 247
robobooga Avatar asked Feb 17 '11 10:02

robobooga


2 Answers

In Perl, function calls have been optimized to not require the & sigil at all times. When you declare a subroutine:

sub hello {print "world\n"}

You can call it as hello; or hello(); or &hello(); which will all do the same thing.

If your subroutine takes arguments, it is a little different:

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!'

So as you can see, using the & sigil is largely redundant, except in the case where there is no argument list. In that case, the subroutine is called with the current values in @_.

The & sigil also has another special behavior, related to Perl's prototypes. Say you were writing your own keys function, and wanted it to behave like Perl's:

sub mykeys (\%) {keys %{$_[0]}}

Here the (\%) prototype tells perl that the first argument to mykeys must be a literal hash (which will be passed in as a hash reference).

my $hashref = {...};

say for mykeys %$hashref;

If for some reason you needed to get around this requirement (generally not the best idea), you could write this:

say for &mykeys( $hashref );  # note that there is no `%`

In this case, adding & before the sub disables the prototype check and any subsequent actions that it would have performed (like taking the reference). In this usage, & is basically an assertion that you know exactly what arguments mykeys needs, and you don't want perl getting in the way.

In general, using & on subroutines should be avoided, unless you explicitly want one of the behaviors I mentioned above.

Finally, & is also needed when you are refering to the actual code reference:

my $coderef = \&hello;

or

if (defined &hello) {print "hello is defined\n"}  # but is not called

As others have mentioned, the my operator declares variables in the current lexical scope. It is required when the use strict; pragma is loaded. Perl has two types of variables, lexical variables declared with my, and package variables.

my variables live in what is called a lexical pad, which is a storage space created by Perl each time a new scope is introduced. Package variables live in the global symbol table.

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

You can use the our keyword to create a lexical alias to a global variable:

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
like image 110
Eric Strom Avatar answered Nov 15 '22 20:11

Eric Strom


The my limits the variable to the current scope. With the use strict pragma, which you should use, you must declare the variables (e.g. with my). The alternative to go without exists for flexibility reasons for very short scripts.

The & is seldom used anymore since Perl default-interprets sigil-less words as subroutines, but is useful if you want to create a reference to subroutine.

sub say_hi { print "hi\n" }
my $sub_ref = \&say_hi;
like image 26
Tim Avatar answered Nov 15 '22 20:11

Tim