Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

why avoid & on function call

by fireblood (Scribe)
on Dec 27, 2020 at 16:20 UTC ( #11125788=perlquestion: print w/replies, xml ) Need Help??

fireblood has asked for the wisdom of the Perl Monks concerning the following question:

Dear wise ones, I've seen a small number of posts in which new users are encouraged not to include a leading ampersand when calling their own user-written functions whose definitions share the same file. One such admonition went as far as saying not to include it "unless you know the difference between using it and not using it and are sure that what it does when you include it is really what you want". Yet I have not seen any explanation of what the difference is between including a leading ampersand and not including it. I've always used a leading ampersand when calling &my_function and have never noticed a problem. Why is the use of a leading ampersand discouraged? What is the difference between including one and not including one? Thank you.

Replies are listed 'Best First'.
Re: why avoid & on function call
by choroba (Cardinal) on Dec 27, 2020 at 16:32 UTC
Re: why avoid & on function call (updated x 3)
by LanX (Sage) 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 :)

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

    Updates

    °) other use case are:

    • calling a post-declared sub without parens().

      E.G. like when wanting to use AUTOLOAD while avoiding parenthesis for syntactic sugar.

    • calling a sub named after a built-in

      E.g. CGI.pm used to have a sub &tr for HTML's "table row" tag which collided with Perl's tr (IIRC)

    • ˛) some built-ins require & with named subs as arguments, like goto, map , grep , sort

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

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: why avoid & on function call
by jdporter (Chancellor) 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.
Re: why avoid & on function call
by hippo (Bishop) on Dec 27, 2020 at 16:58 UTC
    Yet I have not seen any explanation of what the difference is between including a leading ampersand and not including it.

    This tells us that you have not read the relevant FAQ.


    🦛

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.

Re: why avoid & on function call -- defending & syntax
by Discipulus (Abbot) 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.
Re: why avoid & on function call
by Bod (Priest) 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.

      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]
        "The placement of a sub is important only when you call it without parentheses, ..."

        I disagree with the inclusion of the word only in that statement. Here's a situation where placement is important when parentheses are used:

        $ 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

        — Ken

        Bareword use without parens is also the reason why the sub NAME; syntax without function {BODY} exists.

        One can pre-declare functions for the first parse, which are later defined (or resolved via AUTOLOAD)

        DB<188> sub frob; frob(1,2,3); sub frob { say "@_" } 1 2 3 DB<189>

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

      others place them at the start because of the behaviour when not using the ampersand

      Another reason is to avoid accidentally closing over lexical variables declared outside of function scope.


      Improve your skills with Modern Perl: the free book.

      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 &ampersands just to spare parens() has too many side-effects and should be limited to cases which can't be resolved by pre-declaration.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      °) "new" as in "new york", "new model army" or "Bojo Churchill".

        A pre-declaration placeholder can be done by a body-less sub NAME;

        Thanks LanX - I didn't know this was an option. Although in the past I have habitually added an ampersand which I have been doing less and less over the last year or so in favour of always applying parenthesis. So I don't envisage me using this pre-declaration very much but it's good to know it exists.

      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.

        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.

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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11125788]
Approved by LanX
Front-paged by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (8)
As of 2022-12-01 16:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?