Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Unexpected difference in whitespace parsing in subroutine calls.

by Lexicon (Chaplain)
on Jul 10, 2005 at 09:02 UTC ( [id://473740]=perlquestion: print w/replies, xml ) Need Help??

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

There seems to be a difference in the parsing if you put whitespace in between a subroutine name and the subroutine parameters. I imagine this is known, and probably even documented somewhere, but I haven't been able to find it. Can anyone explain the difference?

In case it's a bug: I've run the following code on two machines:
This is perl, v5.8.5 built for i386-linux-thread-multi
This is perl, v5.8.6 built for darwin-thread-multi-2level

#!/usr/bin/perl print (sort ( f( 0 ) )); print (sort ( f ( 0 ) )); print (sort ( &f ( 0 ) )); print (sort f( 0 ) ); print (sort f ( 0 ) ); print (sort &f ( 0 ) ); sub f { 1 }

And get the following results

Chromium:~ lexicon$ perl -l little.pl 1 0 1 0 0 1

Update: No offense guys, but you should read the existing comments before replying to a thread. broquaint had already subtly clued me in that f gets called as the sort subroutine in some cases and noth others. I still find the difference surprising, but etcshadow addressed it as just one of those "crazy rules" perl has for ambiguous situations. etcshadow also pointed out the no op unary + operator which I had been using for years for subroutine calls as my %hash = %{+shift};. Although, really, sort &f(0) does the job and has the bonus of looking correct as well.

Update 2: I thought I should also mention, to those who aren't aware, that this will apply to a lot of situations with built in functions. print will try to call your function to get a file handle, for instance.

All the help is much appreciated, of course!

Replies are listed 'Best First'.
Re: Unexpected difference in whitespace parsing in subroutine calls.
by broquaint (Abbot) on Jul 10, 2005 at 10:24 UTC
    If we deparse this to see how perl will it makes a certain kind of sense
    ## deparse output as deparsed by -MO=Deparse,-p print(sort(f(0))); # case 1 print((sort f 0)); # case 2 print(sort(&f(0))); # case 3 print((sort f 0)); # case 4 print((sort f 0)); # case 5 print(sort(&f(0))); # case 6 sub f { 1; } - syntax OK
    So, cases 1, 3 and 6 all behave the same (i.e call f) and cases 2, 4 and 5 behave the same (i.e sort on 0, which, as a single element list, is already sorted, so f isn't called). And that's the end of that chapter.
    HTH

    _________
    broquaint

      It still doesn't make any sense. I see now though that f is actually getting called in both cases (or would be if there is more than one element). In the runs that return 0, it's called before the sort. In the runs that return 1, it's called as the sorting subroutine. The fact that whitespace indicates precendence really bugs me though. I feel like it should always return one or the other (probaby 1), and that you should be forced to call the subroutine with &.

      To get closer to my original code:

      #!/usr/bin/perl use strict; use warnings; my @list = (1, 2, 1); print join ',', sort (unique (@list)); print join ',', sort (unique(@list)); sub unique { my %new = (); return grep (!$new{$_}++, @_); }
      Returns:
      Chromium:~ lexicon$ perl -l little2.pl Unquoted string "unique" may clash with future reserved word at little +2.pl line 7. 1,2,1 1,2
      With a similar deparse:
      Chromium:~ lexicon$ perl -l -MO=Deparse little2.pl Unquoted string "unique" may clash with future reserved word at little +2.pl line 7. BEGIN { $/ = "\n"; $\ = "\n"; } use warnings; use strict 'refs'; my(@list) = (1, 2, 1); print join(',', (sort unique @list)); print join(',', sort(unique(@list))); sub unique { use warnings; use strict 'refs'; my %new; return grep((!$new{$_}++), @_); } little2.pl syntax OK

      I supose here, in the unique as sort-on-subroutine case, unique always returns a two element list which is probably interpreted as 1 and so leaves the list in order. This ends up looking like the unique subroutine is completely ignored, which drove me nuts for a couple hours.

Re: Unexpected difference in whitespace parsing in subroutine calls.
by revdiablo (Prior) on Jul 10, 2005 at 15:36 UTC

    This is caused by sort. Take a look at the documented calling forms:

    sort SUBNAME LIST sort BLOCK LIST sort LIST

    The extra whitespace is triggering the SUBNAME LIST behavior.

Re: Unexpected difference in whitespace parsing in subroutine calls.
by etcshadow (Priest) on Jul 10, 2005 at 16:27 UTC
    This is yet another example (there have been several of these over the past week or two, huh?) of exercising ambiguities in perl's grammar. The expression you've written could be taken to mean a couple of different things:
    • either a sort being called on the return value of a function called on a list
    • or a sort being called on a list, with a particular function being used as the comparitor in the sort (that is, a function which can be called by sort, to tell it how any two items in the list compare to one another)
    The perl parser has all sorts of crazy rules for determining what it thinks you meant when it runs accross these ambiguous parses. My personal favorite way to disambiguate is with the no-op unary plus operator.
    ------------ :Wq Not an editor command: Wq
Re: Unexpected difference in whitespace parsing in subroutine calls.
by pg (Canon) on Jul 10, 2005 at 16:19 UTC

    The usual suggestion, "use strict; use warnings;". if you d that, you will get warnings, which might lead you to think of something else in this case.

    As for the problem, your f() had two different uses in different cases:

    1. Being used before sort is called. In this case, it returns 1, and that 1 is then sorted.
    2. Being used as call back of sort to determine the order. In your examples, this is not significant, as your list only have one member.

    Look at this very simple example, it shows how the call back is used.

    use strict; use warnings; print sort f (1,2,3); sub f {1}

    Another one (guess output first):

    use strict; use warnings; print sort f (1,2,3,4,5,6); sub f {($b % 2) <=> ($a % 2)}
Re: Unexpected difference in whitespace parsing in subroutine calls.
by holli (Abbot) on Jul 10, 2005 at 09:45 UTC
    I don't know what causes this, but i can reproduce it on ActiveState Perl 5.8.6 on Win XP.


    holli, /regexed monk/
Re: Unexpected difference in whitespace parsing in subroutine calls.
by jhourcle (Prior) on Jul 10, 2005 at 23:18 UTC

    Although I got the same results in 5.8.1, I actually got different results in 5.6.0 :

    001001

    Which, would suggest that although the & forced it to sort the results of the function f(0), means that without the &, it behaves consistently (at least for all of the varients that I tried).

      That's much more what I expect it to do. I was thinking about why this bothers me more than other perl quirks... If there's anything that I expect to disambiguate something, it's parentheses! But in this case adding parens makes it more ambiguous. :)

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (2)
As of 2024-03-19 10:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found