Hacker News new | ask | show | jobs
by BadCRC 5094 days ago
These guidelines won't save you from some bullshit PHP "rules", such as: http://stackoverflow.com/questions/5810168/php-foreach-by-re...
3 comments

How is that a "bullshit PHP rule"? If you for loop in C, setting a pointer each iteration, you would expect the pointer to still be set the the last assignment in the loop once you're out of it.
C lets you define variables with block scope:

  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.
I was thinking more of:

  #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);
  }
Sure, but you defined ptr outside of the loop. Who defined $object outside of the loop in the PHP example?

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.

You think PHP is weird because you don't understand references. Reference is not a pointer, PHP doesn't have pointers. Reference is variable binding. $a =& $b is not an assignment. It is a binding - it means $a and $b are now bound to the same variable/value.
No, I do understand references. I'm just trying to explain how references in PHP are very, very different from references or pointers in any other language I'm aware of, and how they could be confusing to people who know other languages well but are less experienced with PHP.

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?

WTF. Sometimes I wonder if I'm being unfairly prejudiced by not learning PHP myself and making my own decision about it but things like this make me change my mind.
You are completely correct - you are being unfairly prejudiced by judging PHP on explanations of people that do not understand it instead of learning it. If you learned it, you would know references work exactly like they supposed to, and do exactly what they are meant to do - just because they are not, as parent assumes, pointers, he misunderstands them and thinks they are weird. Moreover, he thinks since PHP in not like C and does not have C-like pointers PHP is weird. Please read http://us2.php.net/references if you want real information instead of collection of misunderstanding.
I thought this for a long time as well. I always enjoyed ragging on PHP but wondered if it was just because I wasn't familiar with it.

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.

I'm just upset that you don't have braces around the inner body of your `for` statements. I want to edit the DOM just to fix it.
His indent level is set enough that it's likely not an issue.

(Yes, the "what if you add another statement line later?!" trope has been registered.)

"Yeah, yeah, I know there's a nail in my tired, but I know it's there so it's okay."
There's no bullshit except in that code. If you use by-ref assignment and later try to re-use the same variable name, that's what you get. That's what by-ref binding is designed to do. If you don't understand it, re-read the manual on PHP references. It's not PHP fault if somebody doesn't use language properly.
The result is 100% logical. My own personal guideline is to never use references anywhere; even in a foreach loop you can use the key to modify the original array instead of a reference to the value.
References have their uses, but they are not the simplest concept. For people that think references are like C pointers it is indeed better and safer to never use them. For the rest of people, in about 90% of cases you think you need them you actually don't. But the remaining 10% is still there.
The only place I can see that references still have some value is for "out" parameters on functions. But, since it's easy to do multiple return values in PHP, even that is not terribly relevant.