Вопрос

I would like to know why the following syntax fails

 #!/usr/bin/env perl

use warnings;
use strict;

sub add { return $_[0]+5; };
my $add_ref = \&add;

my $result = 0;

$result = &add(5);
print " result is $result \n";

$result = add(5);
print " result is $result \n";

#$result = $add_ref(5);  ---------------> fail
#print " result is $result \n";

#$result = {$add_ref}(5); -----------------> fail
#print " result is $result \n";

$result =  &{$add_ref}(5);
print " result is $result \n";

$result =  $add_ref->(5);
print " result is $result \n";

1) I have just replaced the name of function add with {$add_ref} which is the method referred in Intermediate Perl book. In a function call & is optional, but why not in this case.

2) I also find that $reference_to_anonymous_subroutine(parameter) works but not $reference_to_names_subroutine(parameter)

Example

my @array = (1, sub { my $n = $_[0]; $n = $n +5;});

my $result = $array[1](2); ---------> works and does not need &{$array[1]}(2)
print "$result \n"; 
Это было полезно?

Решение 2

The problem is that Perl has to make a reliable guess about what you mean.

Given this definition of $add_ref

sub add { return $_[0]+5; };
my $add_ref = \&add;

the "proper" way to call the subroutine would be to use the indirection operator -> which implcitly dereferences its left operand (in a similar way to the "fat comma" => implicitly quoting its left operand).

So you could write the dereference explicitly as

&$add_ref(5)

or do it implicitly with

$add_ref->(5)

Perl always works very hard to work out what you mean by what you write, so I am sure that resolving your statement

$result = $add_ref(5)  # Syntax error

as an indirect subroutine call would have caused a problem with ambiguity.

It is much clearer with your second statement

$result = {$add_ref}(5)  # Syntax error

which which is a syntax error because a bare block can't return a value. (In fact you are declaring an anonymous hash with a single key and no value, and then trying to call it.) If you use do, and the indirection operator then everything is fine. Like this

$result = do{$add_ref}->(5)

but I wouldn't recommend it. Or you could put the block in context, as you did with your next example, and write

$result = &{$add_ref}(5)

which, because the dereference happens first, is identical to

$result = &$add_ref(5)

While Perl references may seem confusing, it will become clearer as you get used to the language. Because of the author Larry Wall's background in linguistics it works very much like a very formal natural language. In every spoken language there are endless "irregular" words, and they have developed that way because the people who use them find it most convenient. There is no other "why", but it is a reason why programmers who have spent less thah a couple months with Perl will quickly denounce it as obscure.

Другие советы

In a function call & is optional, but why not in this case.

In a subroutine call & is optional, but only when you already have the subroutine, not when you need to dereference it first.

The preferred way to dereference something is the -> symbol.

$subroutine_ref->(5); 
$hash_ref->{'key'};
$array_ref->[5];

Of course TIMTOWTDI, and you can dereference with the typed symbol instead of the ->:

 &$subroutine_ref(5);  # same effect as $subroutine_ref->(5)

But I find that less readable.


my $result = $array[1](2); # works and does not need &{$array[1]}(2)

If this goes multiple levels deep, the -> between the parts is implied and optional.

$array[1](2); # shorthand for $array[1]->(2);

You may still need the first one, though: if you have an array reference instead of an array, you'd do

$array_ref->[1](2);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top