Re: [PHP] Strange foreach reference issue

2012-01-09 Thread David Harkness
On Sat, Jan 7, 2012 at 5:01 PM, Tim Behrendsen t...@behrendsen.com wrote:

 The first loop is leaving a reference to the final element. But then the
 second foreach is doing a straight assignment to the $row variable, but
 $row is a reference to the final element. So the foreach is assigning its
 iterated value to the final element of the array, instead of a normal
 variable.


Exactly, and the fact that it shows 1, 2, 2 in the second loop adds more
confusion, but it makes sense. In the second loop, it assigns the indexed
row value into the third row and displays it. Thus it displays row 1, row
2, and then ... row 3, but row 3 is the one that keeps getting overwritten.
And in the third iteration, it overwrites the third row with the third row
which currently holds what was in row 2.

The moral is always unset the iterator variable when doing foreach with a
 reference, like the manual says. :)


While you can certainly follow the above advice, in my view it's dangerous
to have these two loops a) reuse the same variable name for a different
purpose and b) exist in the same scope. More and more I find myself
dropping the subtle tricks I've learned over the years in favor of writing
code that is as easy to understand as possible. Code gets read and modified
a lot more than it gets written, and all those tricks just trip up more
junior teammates--and often even myself. :)

David


Re: [PHP] Strange foreach reference issue

2012-01-09 Thread Tim Behrendsen

On 1/9/2012 10:35 AM, David Harkness wrote:
On Sat, Jan 7, 2012 at 5:01 PM, Tim Behrendsen t...@behrendsen.com 
mailto:t...@behrendsen.com wrote:


The first loop is leaving a reference to the final element. But
then the second foreach is doing a straight assignment to the $row
variable, but $row is a reference to the final element. So the
foreach is assigning its iterated value to the final element of
the array, instead of a normal variable.


Exactly, and the fact that it shows 1, 2, 2 in the second loop adds 
more confusion, but it makes sense. In the second loop, it assigns the 
indexed row value into the third row and displays it. Thus it displays 
row 1, row 2, and then ... row 3, but row 3 is the one that keeps 
getting overwritten. And in the third iteration, it overwrites the 
third row with the third row which currently holds what was in row 2.


The moral is always unset the iterator variable when doing foreach
with a reference, like the manual says. :)


While you can certainly follow the above advice, in my view it's 
dangerous to have these two loops a) reuse the same variable name for 
a different purpose and b) exist in the same scope. More and more I 
find myself dropping the subtle tricks I've learned over the years in 
favor of writing code that is as easy to understand as possible. Code 
gets read and modified a lot more than it gets written, and all those 
tricks just trip up more junior teammates--and often even myself. :)


David

Agreed, in fact, I decided to create a new style naming convention where 
_ref is always suffixed to variable names that are references, along 
with doing the unset, just in case. This goes to show that references 
can be a recipe for subtle bugs to creep in, so best to isolate them as 
much as possible to their own convention. If the convention is followed, 
it should eliminate the possibility of this bug, even if the unset is 
left out.


Tim


Re: [PHP] Strange foreach reference issue

2012-01-08 Thread Adi Mutu
You can see here some nice pics, it's exactly as you said.

http://schlueters.de/blog/archives/141-References-and-foreach.html




 From: Tim Behrendsen t...@behrendsen.com
To: php-general@lists.php.net 
Cc: Stephen stephe...@rogers.com; Matijn Woudt tijn...@gmail.com 
Sent: Sunday, January 8, 2012 3:01 AM
Subject: Re: [PHP] Strange foreach reference issue
 
On 1/7/2012 4:44 PM, Stephen wrote:
 On 12-01-07 07:30 PM, Tim Behrendsen wrote:
 
 When you use an ampersand on the variable, that creates a reference to the 
 array elements, allowing you to potentially change the array elements 
 themselves (which I'm not doing here).
 
 http://www.php.net/manual/en/control-structures.foreach.php
 
 I do notice in the manual that it says, Reference of a $value and the last 
 array element remain even after the foreach loop. It is recommended to 
 destroy it by unset(). But that doesn't really explain why it contaminates 
 the next foreach loop in such an odd way. You would think that the $row in 
 the second loop would be assigned a non-reference value.
 
 Tim
 
 Tim,
 
 You are using the $variable in an unintended (by PHP designers), and I 
 suggest undefined manner.
 
 So the outcome cannot, but definition be explained.
 
 Was this intended, and what were you trying to accomplish?
 
 Stephen

In the real code, I just happen to use the same variable name first as a 
reference, and then as a normal non-reference, and was getting the mysterious 
duplicate rows.

I think I'm using everything in a completely reasonable way; the second foreach 
is reassigning the loop variable. Nothing that comes before using that variable 
ought to cause undefined behavior. The warning in the manual is about using the 
loop variable as a reference after exiting the loop, but I'm not doing that. 
I'm reassigning it, exactly as if I just decided to do a straight assignment of 
$row

Ah ha, wait a minute, that's the key. OK, this is making more sense.

The first loop is leaving a reference to the final element. But then the second 
foreach is doing a straight assignment to the $row variable, but $row is a 
reference to the final element. So the foreach is assigning its iterated value 
to the final element of the array, instead of a normal variable.

OK, I understand the logic now. The world now makes sense. The moral is always 
unset the iterator variable when doing foreach with a reference, like the 
manual says. :)

Thanks for everyone's help.

Tim

-- PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP] Strange foreach reference issue

2012-01-07 Thread Tim Behrendsen

Hello,

This sure looks like a bug, but maybe there's some subtlety going on 
that I don't understand, so I would appreciate some insight. After much 
debugging, I tracked down a bug in my code to this test program. My PHP 
version is 5.3.3, running under Fedora Linux.


?php
$row_list = array(
array(
'Title' = 'Title #1',
),
array(
'Title' = 'Title #2',
),
array(
'Title' = 'Title #3',
) );

printRows at start:  . print_r($row_list, true);
foreach ($row_list as $idx = $row) {
print Title A $idx: {$row['Title']}\n;
}

printRows are now:  . print_r($row_list, true);
foreach ($row_list as $idx = $row) {
print Title B $idx: {$row['Title']}\n;
}
?

When you run the program, it gives the following output:

--
   Rows at start: Array
(
[0] = Array
(
[Title] = Title #1
)

[1] = Array
(
[Title] = Title #2
)

[2] = Array
(
[Title] = Title #3
)

)
Title A 0: Title #1
Title A 1: Title #2
Title A 2: Title #3
   Rows are now: Array
(
[0] = Array
(
[Title] = Title #1
)

[1] = Array
(
[Title] = Title #2
)

[2] = Array
(
[Title] = Title #3
)

)
Title B 0: Title #1
Title B 1: Title #2
Title B 2: Title #2
--

Note that the second foreach repeats the second row, even though the 
index is correct and the print_r shows things as correct.


Now, if you change the name of the reference variable from '$row' to 
'$rowx' (for example), things will work. So clearly there's some issue 
with $row being previously used as a reference that's contaminating 
the subsequent use of $row in the foreach. If there's some logic to 
this, it's escaping me.


Any insight on this would be appreciated.

Regards,

Tim Behrendsen




--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Strange foreach reference issue

2012-01-07 Thread Stephen

I cut and pasted your code and got the same result.

I flipped the two foreach blocks and got the expected results.

I deleted the first block and copied the second, then updated the 
string. I got this. I can't explain.


?php
$row_list = array(
array(
'Title' = 'Title #1',
),
array(
'Title' = 'Title #2',
),
array(
'Title' = 'Title #3',
) );

  printRows are:  . print_r($row_list, true);
foreach ($row_list as $idx = $row) {
print Title A $idx: {$row['Title']}\n;
}

  printRows are now:  . print_r($row_list, true);
foreach ($row_list as $idx = $row) {
print Title B $idx: {$row['Title']}\n;
}

   Rows are: Array
(
[0] =  Array
(
[Title] =  Title #1
)

[1] =  Array
(
[Title] =  Title #2
)

[2] =  Array
(
[Title] =  Title #3
)

)
Title A 0: Title #1
Title A 1: Title #2
Title A 2: Title #3
   Rows are now: Array
(
[0] =  Array
(
[Title] =  Title #1
)

[1] =  Array
(
[Title] =  Title #2
)

[2] =  Array
(
[Title] =  Title #3
)

)
Title B 0: Title #1
Title B 1: Title #2
Title B 2: Title #3



On 12-01-07 06:29 PM, Tim Behrendsen wrote:

Hello,

This sure looks like a bug, but maybe there's some subtlety going on 
that I don't understand, so I would appreciate some insight. After 
much debugging, I tracked down a bug in my code to this test program. 
My PHP version is 5.3.3, running under Fedora Linux.


?php
$row_list = array(
array(
'Title' = 'Title #1',
),
array(
'Title' = 'Title #2',
),
array(
'Title' = 'Title #3',
) );

printRows at start:  . print_r($row_list, true);
foreach ($row_list as $idx = $row) {
print Title A $idx: {$row['Title']}\n;
}

printRows are now:  . print_r($row_list, true);
foreach ($row_list as $idx = $row) {
print Title B $idx: {$row['Title']}\n;
}
?

When you run the program, it gives the following output:

--
   Rows at start: Array
(
[0] = Array
(
[Title] = Title #1
)

[1] = Array
(
[Title] = Title #2
)

[2] = Array
(
[Title] = Title #3
)

)
Title A 0: Title #1
Title A 1: Title #2
Title A 2: Title #3
   Rows are now: Array
(
[0] = Array
(
[Title] = Title #1
)

[1] = Array
(
[Title] = Title #2
)

[2] = Array
(
[Title] = Title #3
)

)
Title B 0: Title #1
Title B 1: Title #2
Title B 2: Title #2
--

Note that the second foreach repeats the second row, even though the 
index is correct and the print_r shows things as correct.


Now, if you change the name of the reference variable from '$row' to 
'$rowx' (for example), things will work. So clearly there's some issue 
with $row being previously used as a reference that's contaminating 
the subsequent use of $row in the foreach. If there's some logic to 
this, it's escaping me.


Any insight on this would be appreciated.

Regards,

Tim Behrendsen







--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Strange foreach reference issue

2012-01-07 Thread Matijn Woudt
On Sun, Jan 8, 2012 at 12:29 AM, Tim Behrendsen t...@behrendsen.com wrote:
 Hello,

 This sure looks like a bug, but maybe there's some subtlety going on that I
 don't understand, so I would appreciate some insight. After much debugging,
 I tracked down a bug in my code to this test program. My PHP version is
 5.3.3, running under Fedora Linux.

 ?php
    $row_list = array(
        array(
            'Title' = 'Title #1',
        ),
        array(
            'Title' = 'Title #2',
        ),
        array(
            'Title' = 'Title #3',
        ) );

    print    Rows at start:  . print_r($row_list, true);
    foreach ($row_list as $idx = $row) {

Why is there an '' before $row here? That seems like the problem to me..

Matijn

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Strange foreach reference issue

2012-01-07 Thread Tim Behrendsen

On 1/7/2012 4:18 PM, Matijn Woudt wrote:

On Sun, Jan 8, 2012 at 12:29 AM, Tim Behrendsent...@behrendsen.com  wrote:

Hello,

This sure looks like a bug, but maybe there's some subtlety going on that I
don't understand, so I would appreciate some insight. After much debugging,
I tracked down a bug in my code to this test program. My PHP version is
5.3.3, running under Fedora Linux.

?php
$row_list = array(
array(
'Title' =  'Title #1',
),
array(
'Title' =  'Title #2',
),
array(
'Title' =  'Title #3',
) );

printRows at start:  . print_r($row_list, true);
foreach ($row_list as $idx =  $row) {

Why is there an '' before $row here? That seems like the problem to me..

Matijn


When you use an ampersand on the variable, that creates a reference to 
the array elements, allowing you to potentially change the array 
elements themselves (which I'm not doing here).


http://www.php.net/manual/en/control-structures.foreach.php

I do notice in the manual that it says, Reference of a $value and the 
last array element remain even after the foreach loop. It is recommended 
to destroy it by unset(). But that doesn't really explain why it 
contaminates the next foreach loop in such an odd way. You would think 
that the $row in the second loop would be assigned a non-reference value.


Tim

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Strange foreach reference issue

2012-01-07 Thread Stephen

On 12-01-07 07:30 PM, Tim Behrendsen wrote:


When you use an ampersand on the variable, that creates a reference to 
the array elements, allowing you to potentially change the array 
elements themselves (which I'm not doing here).


http://www.php.net/manual/en/control-structures.foreach.php

I do notice in the manual that it says, Reference of a $value and the 
last array element remain even after the foreach loop. It is 
recommended to destroy it by unset(). But that doesn't really explain 
why it contaminates the next foreach loop in such an odd way. You 
would think that the $row in the second loop would be assigned a 
non-reference value.


Tim


Tim,

You are using the $variable in an unintended (by PHP designers), and I 
suggest undefined manner.


So the outcome cannot, but definition be explained.

Was this intended, and what were you trying to accomplish?

Stephen

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Strange foreach reference issue

2012-01-07 Thread Tim Behrendsen

On 1/7/2012 4:44 PM, Stephen wrote:

On 12-01-07 07:30 PM, Tim Behrendsen wrote:


When you use an ampersand on the variable, that creates a reference 
to the array elements, allowing you to potentially change the array 
elements themselves (which I'm not doing here).


http://www.php.net/manual/en/control-structures.foreach.php

I do notice in the manual that it says, Reference of a $value and 
the last array element remain even after the foreach loop. It is 
recommended to destroy it by unset(). But that doesn't really 
explain why it contaminates the next foreach loop in such an odd way. 
You would think that the $row in the second loop would be assigned a 
non-reference value.


Tim


Tim,

You are using the $variable in an unintended (by PHP designers), and 
I suggest undefined manner.


So the outcome cannot, but definition be explained.

Was this intended, and what were you trying to accomplish?

Stephen


In the real code, I just happen to use the same variable name first as a 
reference, and then as a normal non-reference, and was getting the 
mysterious duplicate rows.


I think I'm using everything in a completely reasonable way; the second 
foreach is reassigning the loop variable. Nothing that comes before 
using that variable ought to cause undefined behavior. The warning in 
the manual is about using the loop variable as a reference after exiting 
the loop, but I'm not doing that. I'm reassigning it, exactly as if I 
just decided to do a straight assignment of $row


Ah ha, wait a minute, that's the key. OK, this is making more sense.

The first loop is leaving a reference to the final element. But then the 
second foreach is doing a straight assignment to the $row variable, but 
$row is a reference to the final element. So the foreach is assigning 
its iterated value to the final element of the array, instead of a 
normal variable.


OK, I understand the logic now. The world now makes sense. The moral is 
always unset the iterator variable when doing foreach with a reference, 
like the manual says. :)


Thanks for everyone's help.

Tim

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php