When should & be used to call a Perl routine?

I heard that people should not use & to call Perl subs, ie:

 function($a,$b,...); # opposed to &function($a,$b,...); 

I know that the argument list becomes optional, but in what cases is it advisable to use & and cases when you absolutely do not use it?

Also, how does performance increase happen here if you omit & ?

+45
subroutine perl
Aug 28 '09 at 14:32
source share
4 answers

IMO, the only time there is a reason to use & is if you get or call coderef, for example:

 sub foo() { print "hi\n"; } my $x = \&foo; &$x(); 

The main time that you can use, which you absolutely should not in most cases, is to call a subroutine that has a prototype that sets the default behavior to a different one from the standard one. I mean, some prototypes allow you to reinterpret the list of arguments, for example, converting the @array and %hash specifications to links. Thus, sub will expect these reinterpretations to occur, and if you do not go to any length necessary to simulate them manually, sub will receive input data that are very different from those expected.

I think that basically people are trying to tell you that you are still writing in Perl 4 style, and now we have a much cleaner and more enjoyable thing called Perl 5.

In terms of performance, there are various ways in which Perl optimizes the subtitles that & lose, and one of the main ones is nesting constants.

There is also one circumstance where using & provides a performance advantage: if you redirect the foo(@_) with foo(@_) . Using &foo infinitely faster than foo(@_) . I would not recommend it if you have not finally found through profiling that you need this micro-optimization.

+32
Aug 28 '09 at 14:35
source share

I often abuse & , but mainly because I do weird interface things. If you do not need one of these situations, do not use & . Most of them are simply access to a subroutine definition, not a subroutine call. All this in perlsub .

  • Taking a reference to a named routine. This is probably the only common situation for most Perlers:

      my $sub = \&foo; 
  • Similarly, assigning typeglob, which allows you to call a routine with a different name:

      *bar = \&foo; 
  • Checking that the subroutine is defined as you can in the test suites:

      if( defined &foo ) { ... } 
  • Removing a subroutine definition that should not be shared:

      undef &foo; 
  • Providing a dispatcher routine whose sole task is to select the correct routine to call. This is the only situation in which I use & to call a subroutine, and when I expect to call the dispatcher many times and squeeze a small number of operations from the operation:

      sub figure_it_out_for_me { # all of these re-use the current @_ if( ...some condition... ) { &foo } elsif( ...some other... ) { &bar } else { &default } } 
  • To switch to another routine using the current argument stack (and replace the current routine in the call stack), an impractical operation is performed during dispatch, especially in AUTOLOAD :

      goto ⊂ 
  • Call the routine that you named after the built-in Perl. & always gives you custom. This is why we teach it at Learning Perl> . You really do not want to do this normally, but this is one of the features of & .

There are several places where you could use them, but there are better ways:

  • To invoke a routine with the same name as embedded Perl. They just do not have routines with the same name as the built-in Perl. Check perlfunc to see a list of built-in names that you should not use.

  • To disable prototypes. If you do not know what this means or why you want, do not use & . Some black magic code may be needed, but in such cases you probably know what you are doing.

  • To dereference and execute a subroutine reference. Just use the notation -> .

+49
Aug 28 '09 at 19:37
source share

Form & routine () disables prototype validation. This may or may not be what you want.

http://www.perl.com/doc/manual/html/pod/perlsub.html#Prototypes

Prototypes allow you to specify the numbers and types of arguments of a subroutine and check them at compile time. This can provide useful diagnostic assistance.

Prototypes do not apply to method calls or calls made in the old-fashioned style using a prefix.

and you must specify or dereference a subroutine or code link

eg.

 sub foo { # a subroutine } my $subref = \&foo; # take a reference to the subroutine &$subref(@args); # make a subroutine call using the reference. my $anon_func = sub { ... }; # anonymous code reference &$anon_func(); # called like this 

Prototypes are also not applicable to subprogram references.

The subroutine form is also used in the so-called magic goto form.

The goto &subroutine expression replaces the current calling context with a named subroutine call using the current @_ value.

In fact, you can completely switch the call to one subroutine with the call of the named one. This is usually observed in AUTOLOAD blocks, where a delayed subroutine request can be made, possibly with some modification to @_, but it looks at the program completely, as if it were a call to a named element.

eg.

 sub AUTOLOAD { ... push @_, @extra_args; # add more arguments onto the parameter list goto &subroutine ; # change call another subroutine, as if we were never here } 

}

This could potentially be useful for eliminating the tail call , I suppose.

see a detailed explanation of this method here

+16
Aug 28 '09 at 14:39
source share

I have read the arguments against using '&', but I almost always use it. It saves me too much time not to do it. I spend a very large part of my Perl coding time and look for which parts of the code call a particular function. With Lead &, I can find and find them instantly. Without the lead &, I get function definition instructions, comments, and debugging, usually increasing the amount of code I have to check to find what I'm looking for.

The main thing is not to use the '&' you buy, you can use function prototypes. But Perl function prototypes can throw errors as often as they prevent them, because they will take your argument list and reinterpret it like you cannot expect, so calling the function no longer skips the arguments that it literally says it does .

+1
Mar 11 '15 at 3:35
source share



All Articles