Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Tiny Perl puzzle

by Dominus (Parson)
on Jun 05, 2014 at 21:16 UTC ( [id://1088921]=perlmeditation: print w/replies, xml ) Need Help??

Without testing first, guess what this program will print:
print (two + two == five ? "true" : "false")
Then figure out why you were wrong. (Please mark spoilers accordingly.)

Replies are listed 'Best First'.
Re: Tiny Perl puzzle
by tobyink (Canon) on Jun 05, 2014 at 22:19 UTC

    I realised fairly quickly that the plus would be treated as a unary operator, and thus assumed the whole thing would be effectively:

    print two( 0==0 ? "true" : "false" );

    ... and thus Perl would die because there's no function two() defined.

    But how foolish of me!! The first two becomes a file handle of course, albeit an unopened one. So the whole line ends up printing to nowhere.

    Good puzzle. This sort of thing is precisely the reason various best practices have arisen.

    use Moops; class Cow :rw { has name => (default => 'Ermintrude') }; say Cow->new->name
Re: Tiny Perl puzzle (duh)
by tye (Sage) on Jun 06, 2014 at 00:22 UTC

    This surprises any even moderately experienced Perl programmer?

    Update: It appears that my test didn't sufficiently accurately replicate the original program text. Though I admit this particular quirk didn't and doesn't bother me much as I avoid barewords exactly because they lead to lots of ambiguities.

    - tye        

Re: Tiny Perl puzzle
by LanX (Saint) on Jun 06, 2014 at 00:35 UTC
    not sure about the precedence my first guess is "true" my second 1

    Can't test ATM :)

    Cheers Rolf

    (addicted to the Perl Programming Language)

    update

    tobyinc's analysis is correct! :)

    one more reason to enforce use strict and 'warnings'...

      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.

        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

Re: Tiny Perl puzzle
by sundialsvc4 (Abbot) on Jun 06, 2014 at 12:09 UTC
    print (two + two == five) ? ( user == politician) ? "Re-elect me and I will fix it." : "It's not a bug, it's a feature!" : (user == accountant) ? "What do you -want- the answer to be?" : "Don't worry, sonny, no child will be left behind.™" ;
      Another incorrect Perl puzzle?

      (hint: print greedily loves brackets! :)

      Cheers Rolf

      (addicted to the Perl Programming Language)

      (Please mark spoilers accordingly.)

      sundialsvc4, why not honor the OPs request and use spoiler tags?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (6)
As of 2024-04-19 04:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found