Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

(SOLVED) parsing problems with prototype blocks (precedence)

by LanX (Saint)
on Nov 03, 2021 at 12:48 UTC ( [id://11138374]=perlquestion: print w/replies, xml ) Need Help??

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

Hi

I was expecting that a prototype sub foo(&) will parse foo {$x} with precedence foo(sub {$x}) but ...

use strict; use warnings; sub foo (&){ } sub bar {} my ($Q,$t) = (10,2); bar ($Q) + bar ($t); foo {$Q} + foo {$t}; # line 12

C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/sym.pl Too many arguments for main::foo at d:/tmp/pm/sym.pl line 12, near "}; +" Execution of d:/tmp/pm/sym.pl aborted due to compilation errors.

what is happening here?

Is that a bug or a feature?

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

update: s/d/foo/

update

that's unfortunate, prototypes don't seem to influence precedence at all ... :/

use strict; use warnings; sub bla($) {shift} my ($Q,$t,$res) = (10,2); sub tst { print $res= bla $Q / bla $t; } use B::Deparse; print B::Deparse->new('-p')->coderef2text(\&tst);

C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/sym.pl { use warnings; use strict; print(($res = bla(($Q / bla($t))))); }

Replies are listed 'Best First'.
Re: (SOLVED) parsing problems with prototype blocks (updated)
by haukex (Archbishop) on Nov 03, 2021 at 13:57 UTC

    Unfortunately I think you're right, these are just a few additional thoughts.

    that's unfortunate, prototypes don't seem to influence precedence at all

    Nitpick: They do influence precedence/parsing, just not in the way you want - from Prototypes:

    sub mygrep (&@) mygrep { /foo/ } $a, $b, $c sub myrand (;$) myrand 42
    ... treated specially by the parser. mygrep() is parsed as a true list operator, myrand() is parsed as a true unary operator with unary precedence the same as rand() ...
    $ perl -MO=Deparse,-p -e 'sub myrand (;$) {} rand 123 / rand 456; myra +nd 123 / myrand 456' sub myrand (;$) {} rand((123 / rand(456))); myrand((123 / myrand(456))); $ perl -MO=Deparse,-p -e 'sub mygrep (&@) {} grep {$A} + grep {$B} 1; +mygrep {$A} + mygrep {$B} 1' sub mygrep (&@) {} grep( {$A;} grep( {$B;} 1)); mygrep(sub {$A;}, mygrep(sub {$B;}, 1));

    ... so builtins do basically behave the same way in terms of precedence - though as of 5.34 there isn't a builtin with a prototype of (&) or even (&@); grep has no prototype, which indicates it is treated specially by the parser (which is why I had to add the 1 after the above grep lest it be a syntax error instead of Not enough arguments).

    Update: Relevant: Named Unary Operators

      On a similar note, I was once experimenting with constants (i.e. sub(){value} with empty prototype) returning objects with overloaded operators.

      I got bitten by the fact that < was interpreted as the start of of a diamond operator, leading to a compilation error.

      (I showed this here, but can't find the thread ATM)

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

Re: (SOLVED) parsing problems with prototype blocks (precedence)
by ikegami (Patriarch) on Nov 03, 2021 at 16:09 UTC

    «+ foo {$t}» is found where an argument would be. An expression is expected, so «+» is treated as a unary operator, so

    foo {$Q} + foo {$t}

    is the same as

    foo {$Q} foo {$t}

    To get the desired result, you can use the following:

    ( foo {$Q} ) + foo {$t}

    Update: Replaced "Fixed:" with clearer wording.

      UPDATE: I may have misunderstood your post, and FIXED is meant as workaround.

      > Fixed: ( foo {$Q} ) + foo {$t}

      no, it's not, because this was what I expected.

      > + is treated as the unary operator, so

      And it would be binary

      use strict; use warnings; sub foo (&){ shift->()} sub baz (&){ shift->()} sub bar {3} my ($Q,$t,$res) = (10,3); sub tst { ( foo {$Q} ) + baz {$t}; } use B::Deparse; print B::Deparse->new('-p')->coderef2text(\&tst); print tst();
      C:/Strawberry/perl/bin\perl.exe -w d:/tmp/pm/sym.pl { use warnings; use strict; (foo(sub { $Q; } ) + baz(sub { $t; } )); }13

      update
      FWIW I chose + for an example which at least compiles b/c of the ambiguity.

      I originally used / which fails without having any unary meaning (it's seen as the start of a m//)

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

        Yes, by "Fixed: ( foo {$Q} ) + foo {$t}", I meant "You can fix the problem by using ( foo {$Q} ) + foo {$t}"

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (5)
As of 2024-03-28 16:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found