Reputation: 426
please see the below code:
$scalar = 10;
subroutine(\$scalar);
sub subroutine {
my $subroutine_scalar = ${$_[0]}; #note you need the {} brackets, or this doesn't work!
print "$subroutine_scalar\n";
}
In the code above you can see the comment written "note you need the {} brackets, or this doesn't work!" . Please explain the reason that why we cant use the same statement as:
my $subroutine_scalar = $$_[0];
i.e. without using the curly brackets.
Upvotes: 7
Views: 3305
Reputation: 67910
Many people have already given correct answers here. I wanted to add an example I found illuminating. You can read the documentation in perldoc perlref for more information.
Your problem is one of ambiguity, you have two operations $$
and [0]
working on the same identifier _
, and the result depends on which operation is performed first. We can make it less ambiguous by using the support curly braces ${ ... }
. $$_[0]
could (for a human anyway) possibly mean:
${$$_}[0]
-- dereference the scalar $_
, then take its first element. ${$_[0]}
-- take element 0
of the array @_
and dereference it. As you can see, these two cases refer to completely different variables, @_
and $_
.
Of course, for Perl it is not ambiguous, we simply get the first option, since dereferencing is performed before key lookup. We need the support curly braces to override this dereferencing, and that is why your example does not "work" without support braces.
You might consider a slightly less confusing functionality for your subroutine. Instead of trying to do two things at once (get the argument and dereference it), you can do it in two stages:
sub foo {
my $n = shift;
print $$n;
}
Here, we take the first argument off @_
with shift
, and then dereference it. Clean and simple.
Most often, you will not be using references to scalar variables, however. And in those cases, you can make use of the arrow operator ->
my @array = (1,2,3);
foo(\@array);
sub foo {
my $aref = shift;
print $aref->[0];
}
I find using the arrow operator to be preferable to the $$
syntax.
Upvotes: 9
Reputation: 50667
my $subroutine_scalar = $$_[0];
is same as
my $subroutine_scalar = $_->[0]; # $_ is array reference
On the other hand,
my $subroutine_scalar = ${$_[0]};
dereferences scalar ref for first element of @_
array, and can be written as
my ($sref) = @_;
my $subroutine_scalar = ${$sref}; # or $$sref for short
Upvotes: 2
Reputation: 1771
Because $$_[0]
means ${$_}[0]
.
Consider these two pieces of code which both print 10
:
sub subroutine1 {
my $scalar = 10;
my $ref_scalar = \$scalar;
my @array = ($ref_scalar);
my $subroutine_scalar = ${$array[0]};
print "$subroutine_scalar\n";
}
sub subroutine2 {
my @array = (10);
my $ref_array = \@array;
my $subroutine_scalar = $$ref_array[0];
print "$subroutine_scalar\n";
}
In subroutine1
, @array
is an array containing the reference of $scalar
. So the first step is to get the first element by $array[0]
, and then deference it.
While in subroutine2
, @array
is an array containing an scalar 10
, and $ref_array is its reference. So the first step is to get the array by $ref_array
, and then index the array.
Upvotes: 1
Reputation: 386461
${ $x }[0]
grabs the value of element 0 in the array referenced by $x
.
${ $x[0] }
grabs the value of scalar referenced by the element 0 of the array @x
.
>perl -E"$x=['def']; @x=\'abc'; say ${ $x }[0];"
def
>perl -E"$x=['def']; @x=\'abc'; say ${ $x[0] };"
abc
$$x[0]
is short for ${ $x }[0]
.
>perl -E"$x=['def']; @x=\'abc'; say $$x[0];"
def
Upvotes: 2