int main(int argc, char *argv[]) {
for(int i=0;i<10;++i)
printf("%d\n", i);
printf("%d\n", i);
}
The last line fails to compile—'i' is no longer defined after exiting the loop.Java:
public static void main(String[] args) {
for(int i=0;i<10;++i)
System.out.println(i);
System.out.println(i);
}
That also won't compile.Coming from a language that supports variables with block scope, PHP's behavior is very surprising indeed. If the first mention of $object is in the loop, I can understand someone expecting $object in the second loop to be a distinct variable that just happens to share the same name.
This behavior is even surprising coming from Perl, though for a slightly different reason:
@array = ('c', 'c++', 'java', 'perl');
foreach $item (@array) {
if($item eq 'perl') {
$item = 'php';
}
}
foreach $item (@array) {
print $item . "\n";
}
For that matter, PHP's reference semantics are a little surprising in general coming from any other language I've ever used. #include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0}, *ptr;
for(int i = 10; i>=0; i--)
{
ptr = &arr[i];
printf("%d\n", *ptr);
}
printf("%d\n", *ptr);
}Also note that, in C, you have to explicitly dereference pointers:
ptr = 42;
You should get a warning from your compiler if you try that. PHP effectively goes ahead and changes it to: *ptr = 42;
Perl requires you to explicitly dereference references as well: @array = ('c', 'c++', 'java', 'perl');
$item = \$array[3];
$item = 'php'; # Does NOT replace the item in the array
foreach $item (@array) {
print $item . "\n";
}
PHP is weird in this regard: if you ever assign a reference to a variable, later assignments go through that reference automatically. To convert the variable back to a normal variable, you have to unset it. I don't know of another language that acts like this. Can you think of one?Combine that with the lack of block scope, and you get surprises like the example BadCRC linked.
(Well, ignoring operator overloading anyway… you could conceivably import PHP's concept of variables and references into C++.)
A few months ago, I got the opportunity to do a little PHP programming. I was wrong. I didn't have a bad impression of PHP simply out of ignorance. In fact, my opinion of the language is now much lower than before. I honestly can't conceive how anyone could legitimately defend it for anything other than its ubiquity.
Perl does have a similar concept, but it calls it aliasing. Perl references behave more like what you'd expect coming from other languages.
I wish PHP had called its references something else. They're not really references at all.
Just because I think PHP references are weird doesn't mean I don't know how they work. It does make me wonder, though, why PHP references work the way they do. What's the benefit of doing it this way instead of the way just about every other language ever does it?
Most of "other languages" similar to PHP don't even have concept close to references, except for C++. Similarity with C++ may be briefly confusing, but it's not unheard of that in different languages concepts meant to achieve the same thing work differently. Expecting PHP would match C++ in every detail or would have to invent completely new terminology altogether makes little sense.
>> What's the benefit of doing it this way instead of the way just about every other language ever does it?
"Every other language ever" doesn't do it in any particular way. Perl has pointer-like references and they are nightmarish to work with. Languages like Ruby or Java pass everything by value or by object reference depending on how you look on it, since everything is an object. Some don't have the concept of references all. Low-level languages like C/C++ have pointers. In some languages variables are not mutable, so the whole question is moot. Saying that "every other language ever" does some specific thing in this regard and only PHP does it differently is meaningless - different languages do it completely different, and PHP has its own way. It doesn't match your favorite one - fine, everybody is entitled to have one's favorite ways, but that does not make PHP "weird" or wrong in any way, just as it doesn't make C, Java, Python or Perl wrong.
Then it got pointers, and references suddenly weren't needed that much anymore. But it kept the old semantics, and still needs references for passing arrays around, since arrays are not objects, and PHP assignment is still by copy.
(Yes, the "what if you add another statement line later?!" trope has been registered.)