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


Until recently, I've written calls to my subroutines with an ampersand, e.g.

@livesys = sort &Con::liveones;
But Perl Best Practices (p 175) sez Call subroutines with parentheses but without a leading &

I'm running a decrepit Perl, for reasons beyond my control - (5.0 patchlevel 4 subversion 4) and this may be part of my problem, but when I write

@livesys = sort Con::liveones();
I get an empty array. I can work around this (starting with 'If its not broke dont fix it' - leaving the code alone. Or putting the result in a temporary variable, etc.) But what's the Best Practice way?


Replies are listed 'Best First'.
Re: Dropping the ampersand
by ikegami (Patriarch) on Feb 09, 2007 at 21:42 UTC

    sort treats the first parameter specially if it looks like a function name. It uses the function by the specified name as the compare function during sorting. You can use a unary-+ to disambiguate.

    @livesys = sort +Con::liveones;
    is the same
    @livesys = sort { $a cmp $b } Con::liveones;
    with no lost efficiency.

    It's no better and no worse than
    @livesys = sort &Con::liveones;

    Both are better than
    @livesys = sort @{[Con::liveones]};

      You don't lose any efficiency with sort { $a cmp $b }. It's special cased along with several other similar kinds of sorts.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: Dropping the ampersand
by kyle (Abbot) on Feb 09, 2007 at 20:54 UTC

    I can't tell whether this affects you without seeing the rest of your code, but there's a small difference between &foo and foo(). Specifically, &foo will get the current contents of @_ while foo() will not. If Con::liveones is expecting that, then that may be your problem.

    bar( qw( testing is fun ) ); sub bar { &foo; foo(); &foo(); foo( 'woohoo' ); } sub foo { print 'foo: '; print join q{,}, map { "[$_]" } @_; print "\n"; }


    foo: [testing],[is],[fun] foo: foo: foo: [woohoo]
Re: Dropping the ampersand
by imp (Priest) on Feb 09, 2007 at 21:12 UTC
    Perl is very particular about the arguments to sort. In this case perl is interpreting your code to mean that it should use Con::liveones to sort the empty list ().

    You should just store the list in a temporary array, otherwise you'll have to do something hideous like this:

    my @livesys = sort @{[Con::liveones()]};
Re: Dropping the ampersand
by kwaping (Priest) on Feb 09, 2007 at 22:12 UTC
    To illustrate and reinforce imp and ikegami's posts:
    % perl -MO=Deparse -le '@livesys = sort &Con::liveones;' BEGIN { $/ = "\n"; $\ = "\n"; } @livesys = sort(&Con::liveones); -e syntax OK % perl -MO=Deparse -le '@livesys = sort Con::liveones();' BEGIN { $/ = "\n"; $\ = "\n"; } @livesys = (sort Con::liveones ()); -e syntax OK

    It's all fine and dandy until someone has to look at the code.