Re: why avoid & on function call
by choroba (Cardinal) on Dec 27, 2020 at 16:32 UTC
|
The difference is described in perlsub: The ampersand is used to circumvents prototypes or make the current @_ visible to the called subroutine.
What is a prototype, you ask? It's described in the same perlsub, or you can read Far More than Everything You've Ever Wanted to Know about Prototypes in Perl -- by Tom Christiansen.
Forwarding the argument list can be confusing, especially if there's a shift or pop involved, or when calling a functional subroutine from a method.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] |
Re: why avoid & on function call (updated x 3)
by LanX (Saint) on Dec 27, 2020 at 16:32 UTC
|
In Perl 4 the &sigil was mandatory, Perl 5 changed this.
IIRC it has now a bunch of side effects like°
- disabling prototype check when passing arguments
- reusing the caller's @_ when not passing arguments
This can be very useful in edge cases <1‰, but will more likely cause trouble in normal use.
The only time you can't avoid &sigils in standard Perl5 is when referencing a named function ˛
$code_ref = \&sub_name
More in perlsub ...
HTH :)
Updates
°) other use case are:
| [reply] [d/l] [select] |
|
defined &func, exists &func, and goto &func (distinct from the troublesome goto LABEL) are some other examples when you would use the ampersand to refer to a named function. -Dan
| [reply] |
|
> are some other examples when you would use the ampersand to refer to a named function.
goto was already mentioned :)
> > ˛) some built-ins require & with named subs as arguments, like goto, map , grep , sort
| [reply] |
Re: why avoid & on function call
by jdporter (Paladin) on Dec 27, 2020 at 16:33 UTC
|
Please read perlsub.
Not only does the & form make the argument list optional, it also disables any prototype checking on arguments you do provide. This is partly for historical reasons, and partly for having a convenient way to cheat if you know what you're doing.
I'm not going to quote the entire thing, so, please go read perlsub.
I reckon we are the only monastery ever to have a dungeon stuffed with 16 ,000 zombies.
| [reply] [d/l] |
Re: why avoid & on function call
by hippo (Archbishop) on Dec 27, 2020 at 16:58 UTC
|
| [reply] |
Re: why avoid & on function call
by stevieb (Canon) on Dec 27, 2020 at 17:42 UTC
|
"What is the difference between including one and not including one?"
The difference is that people who are more experienced can tell that you're learning from a book published in 1998 when you're using it out of a legitimate context in 2020 ;)
In all seriousness, this is a good, valid question, because I still see new questions pop up from time-to-time on various sites who use this technique. It's usually combined with a lack of strict and declaring/defining variables without my.
| [reply] [d/l] [select] |
Re: why avoid & on function call -- defending & syntax
by Discipulus (Canon) on Dec 28, 2020 at 10:55 UTC
|
Hello fireblood,
> I've always used a leading ampersand when calling &my_function and have never noticed a problem.
Me too I was used to code this way, even if discouraged many times by other monks. I knew the eventual pitfalls and all differences between the two syntax.
I always used &my_func( 42 ) to highlight that sub was defined in the current file and not coming from an external module ( update: I found this very useful in my first years of programming, when the whole mess of internal functions, local and imported subs was difficult to distinguish at glance ).
Many perl programmers hate this syntax, telling you to avoid it: this is not true. The & is optional
> A subroutine may be called using an explicit & prefix. The & is optional in modern Perl, as are parentheses if the subroutine has been predeclared. The & is not optional when just naming the subroutine, such as when it's used as an argument to defined() or undef(). Nor is it optional when you want to do an indirect subroutine call with a subroutine name or reference using the &$subref() or &{$subref}() constructs, although the $subref->() notation solves that problem.
The above quote from perlsub states it clearly and tell us even more: you must know this syntax because sometimes it must be used.
So, imho, you have not to avoid it but you have to be aware of what it implies and you got good answers about it.
Extending a bit what perlsub says you can have the following:
NAME(LIST); # & is optional with parentheses.
NAME LIST; # Parentheses optional if predeclared/imported.
&NAME(LIST); # Circumvent prototypes.
&NAME; # Makes current @_ visible to called subroutine.
defined(&NAME); # & is needed. The same is valid for undef(&NAME) and
+ any case when you are naming your sub
&$subref(); # & is needed. But $subref->() can be used to avoid t
+he &
&{$subref}(); # & is needed. But $subref->() can be used to avoid t
+he &
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] [select] |
Re: why avoid & on function call
by Bod (Parson) on Dec 27, 2020 at 17:08 UTC
|
From a rather limited viewing of other people's code, I have noticed that some Perl programmers tend to place their subroutines at the start of the code. Personally I have always tended to place them at the end and have always assumed others place them at the start because of the behaviour when not using the ampersand.
| [reply] |
|
The placement of a sub is important onlymainly when you call it without parentheses, i.e. as a bareword. When such a call is being parsed, the subs already parsed are recognised and the bareword is parsed as their call, otherwise without strict, the bareword is stringified, and with strict, you get an error.
#!/usr/bin/perl
use warnings;
print "", frob(); # 12
print "", frob; # frob
use strict;
print "", frob(); # 12
# print "", frob;
sub frob {
12
}
Uncommenting the last last print line would make the source unparsable with Bareword "frob" not allwoed while "strict subs" in use
Updated: as shown in the text, thanks kcott.
map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
| [reply] [d/l] [select] |
|
$ perl -wE '
sub meaning () { 42 }
say meaning();
'
42
$ perl -wE '
say meaning();
sub meaning () { 42 }
'
main::meaning() called too early to check prototype at -e line 2.
42
You can, of course, predeclare and leave the definition for later:
$ perl -wE '
sub meaning ();
say meaning();
# ... later in code with other subroutine defintions
sub meaning () { 42 }
'
42
| [reply] [d/l] [select] |
|
DB<188> sub frob; frob(1,2,3); sub frob { say "@_" }
1 2 3
DB<189>
| [reply] [d/l] [select] |
|
| [reply] |
|
Post-declared subs are always resolved as long as Perl knows that it's a sub, that's why Perl5 introduced the "new syntax" ° with parenthesis func()
Pre-declaration is only necessary when avoiding parens in bareword use, like func 1,2,3 because otherwise Perl can't tell at the first parse if its a sub-call or not.
A pre-declaration placeholder can be done by a body-less sub NAME; or with the pragma use subs LIST for multiple names.
Using &ersands just to spare parens() has too many side-effects and should be limited to cases which can't be resolved by pre-declaration.
°) "new" as in "new york", "new model army" or "Bojo Churchill".
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
|
Putting subroutines first was important back in the days when compilers were less advanced. So you declared a bunch of routines at the top of the file, and then at the end of your file you had the main routine that called them all.
These days, that's not necessary. From a style point of view (he said, donning his asbestos firesuit), I like having the 'main' part of the routine first, so that at a quick glance of the file, I can see what's going on. If I want further detail, I can scroll down to look at the routines I'm interested in.
And to address the use of '&', the short answer is Don't Use It. The long answer is, Use It If You Understand What It's Doing And You Actually Really Do Need That Behaviour.
Alex / talexb / Toronto
Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.
| [reply] [d/l] |
|
From a style point of view (he said, donning his asbestos firesuit), I like having the 'main' part of the routine first, so that at a quick glance of the file, I can see what's going on. If I want further detail, I can scroll down to look at the routines I'm interested in.
We style things the same :)
It is very rare that I arrange code differently to this.
Usually I add an explicit exit statement to the end of the 'main' part of the code before the subroutines so it is obvious where the 'main' block ends.
| [reply] [d/l] |
|
|
|
Re: why avoid & on function call
by fireblood (Scribe) on Dec 28, 2020 at 12:45 UTC
|
Dear all, thank you for the many responses, some with code examples, some with references to other sources of relevant information. This has been extremely valuable for me. -fireblood | [reply] |