Strange interaction between print and the ternary conditional operator
Asked Answered
A

2

1

Ran into a strange interaction between print and the ternary conditional operator that I don't understand. If we do...:

print 'foo, ' . (1 ? 'yes' : 'no') . ' bar';

...then we get the output...:

foo, yes bar

...as we would expect. However, if we do...:

print (1 ? 'yes' : 'no') . ' bar';

...then we just get the output...:

yes

Why isn't " bar" getting appended to the output in the second case?

Aphra answered 20/2, 2020 at 3:20 Comment(1)
First form is (print (1 ? 'yes' : 'no')) . ' bar', but you are looking for print ((1? 'yes' : 'no') . ' bar') -- Operator Precedence and Associativity.Rhynchocephalian
F
9

Let's do it, but for real -- that is, with warnings on

perl -we'print (1 ? "yes" : "no") . " bar"'

It prints

print (...) interpreted as function at -e line 1.
Useless use of concatenation (.) or string in void context at -e line 1.
yes

(but no newline at the end)

So since (1 ? "yes" : "no") is taken as the argument list for the print function then the ternary is evaluated to yes and that is the argument for print and so that, alone, is printed. As this is a known "gotcha," which can easily be done in error, we are kindly given a warning for it.

Then the string " bar" is concatenated (to the return value of print which is 1), what is meaningless in void context, and for what we also get a warning.

One workaround is to prepend a +, forcing the interpretation of () as an expression

perl -we'print +(1 ? "yes" : "no") . " bar", "\n"'

Or, call the print as function properly, with full parenthesis

perl -we'print( (1 ? "yes" : "no") . " bar", "\n" )'

where I've added the newline in both cases.

See this post for a detailed discussion of a related example and precise documentation links.

Fluff answered 20/2, 2020 at 3:28 Comment(0)
B
2

If the first non-whitespace character after a function name is an opening parenthesis, then Perl will interpret that as the start of the function's parameter list and the matching closing parenthesis will be used as the end of the parameter list. This is one of the things that use warnings will tell you about.

The usual fix is to insert a + before the opening parenthesis.

$ perl -e "print (1 ? 'yes' : 'no') . ' bar'"
yes
$ perl -e "print +(1 ? 'yes' : 'no') . ' bar'"
yes bar
Bodyguard answered 20/2, 2020 at 8:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.