in reply to Re: Tiny Perl puzzle
in thread Tiny Perl puzzle

I wasn't even trying to guess what it would really parse as so I just Deparse and run it

$ perl -MO=Deparse print (two + two == five ? "true" : "false") ^Z print two 'two' == 'five' ? 'true' : 'false'; - syntax OK $ perl -MO=Deparse,-p print (two + two == five ? "true" : "false") ^Z print(two (('two' == 'five') ? 'true' : 'false')); - syntax OK $ perl -w print (two + two == five ? "true" : "false") print (...) interpreted as function at - line 1. Unquoted string "two" may clash with future reserved word at - line 1. Unquoted string "two" may clash with future reserved word at - line 1. Unquoted string "five" may clash with future reserved word at - line 1 +. ^Z Name "main::two" used only once: possible typo at - line 1. Argument "five" isn't numeric in numeric eq (==) at - line 1. Argument "two" isn't numeric in numeric eq (==) at - line 1. print() on unopened filehandle two at - line 1.

Replies are listed 'Best First'.
Re^3: Tiny Perl puzzle
by davido (Cardinal) on Jun 06, 2014 at 18:43 UTC

    I think B::Deparse gets it wrong -- as it sometimes does -- when you add -p:

    My theory: When Deparse tries to add parens wherever it can, it treats the first two as a function call (which was my first guess too). But as tobyink correctly surmised, that first two is treated by print as a filehandle.

    This is confirmed by the more low-level output of B::Concise:

    $ perl -MO=Concise,-exec, -e 'print ( two + two == five ? "true" : "fa +lse" )' 1 <0> enter 2 <;> nextstate(main 1 -e:1) v:{ 3 <0> pushmark s 4 <$> gv(*two) s 5 <1> rv2gv sKR/1 6 <$> const(PV "two") s/BARE 7 <$> const(PV "five") s/BARE 8 <2> eq sK/2 9 <|> cond_expr(other->a) lK/1 a <$> const(PV "true") s goto b d <$> const(PV "false") s b <@> print vKS c <@> leave[1 ref] vKP/REFC -e syntax OK

    It's easy to see from this output that the first two is treated as a typeglob; a filehandle. The second two and the five are treated as barewords; constants in this case, which are then compared to one another. They evaluate to the same constant defined value, which is probably an empty string, equating to 0 for the purpose of numeric equality. So "true" will result, but it's printed to a filehandle that hasn't been attached to anything.


    Dave

      Look at the way Deparse uses whitespace, its subtle

      My theory: When Deparse tries to add parens wherever it can, it treats the first two as a function call (which was my first guess too). But as tobyink correctly surmised, that first two is treated by print as a filehandle.

      That is not the way I read it :) Usually, Deparse doesn't add extraneous space to function calls, its always "foo( ... )" its never "foo ( ... )"

      so the way I read that deparse output is as filehandle not function call

      For example

      $ perl -MO=Deparse 2 sub two { rand; } print two(two() == 'five' ? 'true' : 'false'); 2 syntax OK $ perl -MO=Deparse,-p 2 sub two { (rand); } print(two(((two() == 'five') ? 'true' : 'false'))); 2 syntax OK

      When I look at Re^2: Tiny Perl puzzle I see  print( filehandle ... );

      I don't think so.

      did you recompile the output?

      I can't test ATM, but most likely it depends if a function is known at compile time. Contrary to AnoMonk I doubt space matters.

      Anyway IMHO the indirect object syntax should be deprecated....

      Cheers Rolf

      (addicted to the Perl Programming Language)

        I can't test ATM

        You gotta stop saying that :)

        Contrary to AnoMonk I doubt space matters.

        Sure it does, it matters how Deparse places the space, because it matters to perl

        $ perl -w print(two (('two' == 'five') ? 'true' : 'false')); Unquoted string "two" may clash with future reserved word at - line 1. ^Z Name "main::two" used only once: possible typo at - line 1. Argument "five" isn't numeric in numeric eq (==) at - line 1. Argument "two" isn't numeric in numeric eq (==) at - line 1. print() on unopened filehandle two at - line 1.
        That is exactly as deparsed with -p, behaves exactly like the original