echo '1'.print(2) + 3; shows "511"???

Hi I came across this on the internet… can anybody explain the logic behind this and also why the people who made PHP made echo and print act like this? It seems like print and/or echo also return a value as well as printing to the screen…

echo '1'.print(2) + 3; // 511
echo '<br><br>';
echo '2'.print(2) + 3; // 521
echo '<br><br>';
echo '1'.print(2) + 1; // 311
echo '<br><br>';
echo '1'.print(2) + 2; // 411
echo '<br><br>';
echo '1'.print(0); // 011
echo '<br><br>';
echo '1'.print(1); // 111
echo '<br><br>';

BTW I’ve noticed that things like echo (5==5) result in 1 being printed.

also:

$d = print(4) + print(4) + print(4) + print(4);
echo '---'.$d; // 4555---1

echo (5==5) displays the truth value of “five equals five”, I guess…

Yeah that one is fairly straight-forward… BTW echo (5==4) prints nothing at all.

print(99) + print(99) + print(99) + print(99);

shows 99100100100…

I was beginning to ask it on stackoverflow and found this:
“Why does “echo ‘2’ . print(2) + 3” print 521?”

In PHP, “print” and “echo” are both not real functions, but “language constructs”. You don’t need to put parentheses around their arguments. Furthermore, “print” always returns 1 as a return value.

If “print” were a real function, then “print(2) + 3” would first output the value 2. However, because it is not a function, this statement actually gets interpreted as identical to “print ((2) + 3)” so it will print 5.

Now for the full statement:

echo ‘1’.print(2) + 3;

First the expression “(2) + 3” gets evaluated, returning 5. This gets passed into the ‘print’ construct, so it goes to the output. Then ‘print’ returns 1, which gets concatenated to the ‘1’ which is already there, so the string “11” is what gets passed into the ‘echo’ construct. So you get first a 5, then “11”, printing “511” as a whole.

Thanks BTW about my other query… it is similar to:
print(10) + print(20) + print(30) + print(40); which results in 40312111
It is evaluated from right to left adding on the 1’s which the prints return.

This has nothing to do with print not being a “real function”–print has a similar status in Perl and yet works correctly (“print(2) + 3” prints 2 and evaluates to 4). Print behaves that way in PHP because PHP is the worst language in common use and is filled with that kind of nonsense.

That just means that Perl apparently treats it like a function when you write it as a function. It means that Perl tries to figure out what you actually meant instead of just what you wrote. That would make Perl a higher level language than PHP, which doesn’t surprise me at all, knowing what I know about the language.

Some people actually prefer lower level languages that don’t help you out to higher level languages that do. They like their languages to be strict. They claim it teaches them to code more optimally.

It is about whether it is a function or not - if it was a function it would handle the brackets like in Perl.

Print in Perl also behaves differently than “real” functions; the way you specify a non-default filehandle is different than ordinary functions. But it handles parenthesis the way functions do.

My point is that the designers of PHP could have chosen to make print behave consistently and logically when it comes to parenthesis, and they didn’t. It’s a design choice, and they chose poorly. The same would be true whether print was an operator, a function, or a “language construct” (whatever that is).

The documentation is shit as well. See this. Specifically, it says:
print is not actually a real function (it is a language construct) so you are not required to use parentheses with its argument list.

How utterly misleading! It merely says that parens are optional. Someone who didn’t know better might think that implies it behaves like a function when parens are specified. Nope! And there isn’t even an example provided that demonstrates the differing behavior.

Ah ha ha ha ha! PHP is exactly the opposite of a strict language. It is not even strictly specified, or consistently specified for that matter. It is, in fact, a poor ripoff of Perl.

As far as languages go, Perl and PHP are equally “high” (they are both interpreted scripting languages with weak typing). However, Perl has a “use strict” mode that at least enforces certain good coding practices, such as explicit variable declaraction.

The issue here isn’t that print doesn’t behave like a function. Print in Perl doesn’t behave like a function, either. The issue is that parentheses don’t behave like parentheses.

I am hardly a PHP fan, so I feel no particular compulsion to jump to its defense. And indeed this distinction between ‘language constructs’ and functions strikes me as a bit inelegant.

But are you sure you want to hold up Perl, of all scripting languages, as the shining beacon which PHP should attempt to live up to in this regard? Perl has plenty of idiosyncrasies of its own. In fact it is famous, more than any other language that I know of, for containing so many little “helpful” tweaks and special cases in its parser that you can never be entirely sure what it is going to do with a given piece of code. Unlike Python or Ruby, for example, there is no formal language specification for Perl 5; basically the only way to find out what a piece of code is going to do, is to run it and see what happens.

In fact, on the topic of whether or not ‘print’ behaves like a function as far as the precedence of the parentheses is concerned, Perl has a particularly hairy special case of its own:

(From Programming Perl, chapter 2. The sarcastic footnote is part of the quote.)

So in Perl,

and

will be treated differently, violating the language’s general rule that whitespace between tokens is not significant and there is no distinction between spaces, tabs and newlines.

Now, don’t get me wrong – I like Perl, it has lots of cool features and I do prefer it over PHP myself. (Although I prefer Python and Ruby over both.) But when it comes to counter-intuitive parser behavior, maybe Perl programmers are not in the best position to throw stones… :stuck_out_tongue:

Impressive! I’ll admit: I didn’t know about that example. I’ll submit that one runs across these idiosyncracies far less often in Perl than PHP, but even so, violating the whitespace rule in any situation is… not good (a reason I’m not a fan of Python, though I have no comment about its consistency).

That said, my intent was not to hold Perl up as a “shining example” of consistency :).

I’m a bit late to the party, and I don’t particularly like to defend PHP, but in this situation, parentheses behave just like they should – if print is an operator and not a function. Think of it this way, to the parser, “print(2) + 3” is equivalent to “~(2) + 3”. The parenthesis ought to override operator precedence but it only encapsulates a single token.

The “problem” is that “print” is in fact a unary operator, but its precedence is low, so that whereas “~2 + 3” is parsed as “(~2)+3”, “print 2 + 3” is parsed as “print (2 + 3)”.

That’s a fair way of looking at it. In C, all unary operators have precedence between parens and everything else. Hence, they all behave like functions when you provide extra parentheses. In PHP (and Perl), for print, they wanted to retain some of the form of the old shell languages, where “echo” had a similarly low precedence. That’s all fine, but in Perl they special-cased it so that if you use it like a function (or a C-like unary operator), it behaves like one. In PHP, they chose not to do that, so that it may actually be impossible to resolve precedence issues by applying extra parentheses.

To be honest, my point from the beginning was just that if print is a “language construct” (which to me means it’s not a function or operator; it’s a special-cased thing of its own), then the language designers could have chosen an implementation that behaves more like other constructs. It doesn’t have to fit into the normal hierarchy of precedence. That’s what Perl did, and why it behaves in a more “do what I mean” fashion (Walton Firm’s objection notwithstanding). The PHP designers didn’t do that.

If I write

what I almost certainly want is to print the value 35, rather than to print 5 and then multiply the (meaningless) return value of the print command with 7 and discard the outcome. So in that sense, PHP is the “do what I mean” language in this case.

The only situation where the result is arguably surprising, is in this highly contrived case where print is used as a function inside a larger expression, despite the fact that there is no reason why you would ever do that in a real program, given that it has no meaningful return value. The expression given in the thread title is not something you will ever encounter in real code, but only as a puzzle to trick programmers with.

I guess what the PHP designers could have done, is to simply make it an error to use the return value of ‘print’ or ‘echo’ as part of a larger expression. But looking at the list of PHP keywords, there aren’t many language constructs which would make sense to use as part of a compound expression (maybe eval is an exception) so the issue is not likely to come up very often.

Sure, it’s a logical comparison operator; what you’re saying is “does 5 equal 5?” with the return value of 1 if true, 0 if false.

So echo (5==4) would display 0, I’d think.

Perl and PHP both have strong typing in that programs always fail in defined and controlled ways, as opposed to C, where you can use casts to make programs fail in ways which can’t be controlled because you’ve gone beyond what the language’s runtime can control, and what happens next is up to the OS, the hardware, or both.

What Perl and PHP don’t have which Haskell, for example, has is static typing. Haskell has strong static typing, C has weak static typing, Perl and PHP have strong dynamic typing, and off the top of my head I can’t think of any language with weak dynamic typing.

C has strong typing: every variable has a clearly defined type, and the compiler makes sure that, under normal conditions, you cannot perform an operation on a variable which is not valid for its type. In most cases, C is more conservative in what it will allow qua explicit casting than e.g. Perl.

Just because there are some low-level facilities which allow you to bypass the normal type safety rules, doesn’t mean the language is not strongly typed. If somebody wrote a Perl module which allowed you to do casting in Perl, would the existence of that module (even though you’re not forced to use it, and it won’t do anything until you explicitly invoke it in your code) make the entire language not strongly typed anymore?