Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

A question of style

by myocom (Deacon)
on Aug 23, 2000 at 02:50 UTC ( [id://29126] : perlquestion . print w/replies, xml ) Need Help??

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

This may be better placed as a Meditation, but here goes...

It is written in perlstyle, "Call your subroutines as if they were functions or list operators to avoid excessive ampersands and parentheses."

Personally, I like using the ampersands for my functions and subs because it serves as a visual cue that it's my code being executed and not a built-in function or somesuch. However, I have heard other people refer to ampersands as being Perl4-ish and generally unnecessary in this day and age.

What are your thoughts? I await enlightenment.

Replies are listed 'Best First'.
(tye)Re: A question of style
by tye (Sage) on Aug 23, 2000 at 05:38 UTC

    Updates added (inside bolded parens).

    Okay, this is rumor control: (:

    1. Using ampersand and parentheses can be good when calling a user-defined subroutine with a name that is all lowercase (or all uppercase) because otherwise you might unintentionally invoke a current or future built-in function by mistake. (Using an underscore in the name makes this less likely but I'm not convinced that we won't see more built-ins with underscores in their names.)
    2. Using ampersand without parentheses (as already noted) is a special form for reusing the value of @_ and should only be used for advanced purposes.
    3. Ampersand is required for certain operations involving references to functions: for taking a reference to a function ($ref= \&func) and then using that reference (&$ref(...)), though the second item can be written as $ref->(...) for recent versions of Perl.
    4. Using neither ampersand nor parentheses requires that the subroutine be predeclared. This can be very handy because with use strict 'subs', this means that your typos are caught at compile time instead of at run time (where you might not notice them for quite a while if that part of your code is seldom executed). (However, predeclaring subroutines can be tricky and turn into a maintenance problem. Putting most of your subroutines into modules can make this easier.)
    5. Adding an ampersand can break code because it disables function prototypes. If you are not certain that a function isn't prototyped, then you shouldn't use an ampersand on it. This means that it is a bad idea to make subroutines with all-lowercase names (or all-uppercase names) that have prototypes. Prototypes are rarely used (except for making constants -- where overriding them isn't very bad, just removing a performance optimization) but you can still get bit by this.
    6. I see places where a lack of parens makes the code easier to read (when you have functions that like to be stacked similar to
      print map {} sort {} map {} grep {} @list;
      ). However, the lack of parens is more likely to make the code harder to maintain (makes it easy to make precedence errors -- especially since the precedence of a function call can change based on its prototype). Note the two errors introduced below:
      print map {} sort {} map {} grep {} @list, "\n" || die;
    7. Ampersand is considered "old" style because it wasn't too long ago when you had to use ampersand to call a user-defined subroutine (gee, I've reused that part of my brain already; I think ampersand was first made optional with perl5). (However, there are some good reasons to use & for subroutines listed above. Another reasonable justification would be because you like having a visual distinction between built-ins (can't have &) and user-defined subroutines.)

    Sorry, it just seemed like a lot of speculation was flying about, some correct, some wrong, some just unexplained.

            - tye (but my friends call me "Tye")
      Thanks, tye, for your most helpful feedback.


      13 years and many Perl releases later, is this still a fair summary of best practice? I at a client site, ploughing through a lot of recently written code, that is using the &sub calling technique for pure cargo cult reasons. Is it worth trying to change local thinking?


      Pereant, qui ante nos nostra dixerunt!
(Ovid) Re: A question of style
by Ovid (Cardinal) on Aug 23, 2000 at 03:07 UTC
    I generally prefer to use parens, but be aware that the following two statements are not identical:
    &mysub; mysub();
    If you call a sub with empty parentheses, the called sub has an empty @_. However, if you call it with a preceding ampersand as in the first example, the current value of @_ gets passed to the sub that you call. This is most useful when calling subs from subs.

    This is more than just a matter of style. If you're not aware of that difference, coming back later to maintain that code may just break it. As a result, I prefer not to use ampersands when calling a sub unless I specifically desire to pass the contents of @_ to the called sub.


Re (tilly) 1: A question of style
by tilly (Archbishop) on Aug 23, 2000 at 02:58 UTC
    Well when a question of what advice to give on maintainability came up on perl5-porters, the most common response was, "Tell them to use parentheses." In fact perlstyle also tells you not to omit unnecessary parentheses. :-)

    Personally I tend to not want to worry about predeclaring functions with strict, so I use & and parens. YMMV.

    My other differences from perlstyle are that I tend to use a 2-space indent to match co-workers rather than the 4-space indent in perlstyle, and I am in the habit of using redundant punctuation.

Re: A question of style
by ZZamboni (Curate) on Aug 23, 2000 at 03:03 UTC
    I think it's entirely a matter of personal taste. I also try to avoid the ampersand whenever possible, using parenthesis after its name (empty if there are no arguments) to make it clear that it's a function call.

    There is at least one case, though, in which the ampersand has a very specific use: if you write "&func" (this is, with ampersand and without parenthesis) the function will be called with the contents of @_ as arguments. I don't know where this is documented; I learned it from Conway's OO-perl book.

    Other uses for the ampersand include de-referencing code references.


Re: A question of style
by chromatic (Archbishop) on Aug 23, 2000 at 04:13 UTC
    I generally only use the ampersand when I'm calling a subroutine via a reference. The rest of the time, I follow perlstyle and put parenthesis on user-defined subroutines, even when I pass an empty argument list.

    Idiomatic Perl is good, but I haven't seen enough people using the &subname-passes-@_ behavior often enough to use it regularly.

    Sometimes, I even use $sub_ref->(), but that's just silly.

Re: A question of style
by turnstep (Parson) on Aug 23, 2000 at 14:55 UTC

    Excellent post by tye

    I almost always use an ampersand because I think of it as another "type" delmiter - scalars start with a dollar sign, arrays with an "at", hashes with a percent, typeglob with a star, and subroutine with an ampersand. Why file handles did not get their own little symbol is still a mystery. :)

    I also believe that it is required when you undef a subroutine, FWIW

      I think that's the subconscious reason I use ampersands as parallels nicely in my mind to the other type-punctuation.
RE: A question of style
by Adam (Vicar) on Aug 23, 2000 at 02:55 UTC
    I like to use parens with my functions. I find it very readable. But I'm not very obsessive about it. Sometimes I drop the parens, sometimes I use an ampersand. But I like the look and explicit nature of the parens.
Re: A question of style
by maverick (Curate) on Aug 23, 2000 at 03:02 UTC
    I tend to use parens and & on my functions. I think it makes it easier on whoever has to read my code next. The parens remove any perceived ambiguity(sp?) about function params and the & clearly seperates which functions I've written from any built in ones.

    IIRC there was some difference about using the & in Perl 4, something to do with the order in which perl tried to find the code for it, or something. (perhaps merlyn will clear this part up).


      ampersand was always required in Perl4. Perl5 made it optional, as long as you either have the subroutine declaration in scope or parens following the name.

      -- Randal L. Schwartz, Perl hacker

Re: A question of style
by Nooks (Monk) on Aug 23, 2000 at 04:59 UTC
    > Sometimes, I even use $sub_ref->(), but that's just
    > silly.

    I used that syntax just last night to make it really clear that $sub_ref was a reference to a subroutine (it was going to be a small demonstration of a sub returning a closure to implement an easily-implemented memoization cache).