Re: [PHP] foreach() using current() strange beahvior

2007-06-24 Thread Julien Pauli

Don't worry I know how variable work internaly into Zend Engine ( for those
who want more info, Derick Rethan's got a good pdf file explaining that
process here :
http://derickrethans.nl/files/phparch-php-variables-article.pdf , Derick, if
you here us, feel free to come in that conversation ;-) )

But as said, that is an internal PHP behavior that, in my opinion, should be
explained in the documentation.
Now consider this :

$v) {

   if (current($a) == current($b)){ // I want you to stop on the second key
of $b
   var_dump(current($b)); // will never get echoed, as current($a)
always returns String"One"
   break;
   }

}
?>

Due to COW, using current($a) makes PHP making a "real" copy of $a array to
work on it, and current($a) is always at its first place ( String"One")
because PHP works on the "real" copy, and its own array iterator. In that
example, the if condition will never be satisfied.
Ok let's make it funnier now :

$v) {

   if (current($a) == current($b)){
   var_dump(current($b)); // works : outputs String"Two"
   break;
   }

}

var_dump(current($a)); // output String"Two"
?>

Aha, now if I hold a reference to $a variable ($c here ), it looks like COW
doesn't show the same behavior as before.
Foreach seems to keep working on a "lazy" copy of $a, and so it moves the
real $a internal iterator as shown here. The if condition is verified and
the last script line clearly shows that $a internal pointer has been
manipulated by the foreach loop.


We see here that working on internal iterators using foreach is not really
recommanded. I have never needed to do that in a real developpement as well,
I'm just experimenting PHP behavior, but I think that the official
documentation should warn users about such behaviors.

For information : it's actually tested, for me, on PHP 5.2.3 running on a
Windows server. Error Reporting is set to E_ALL.

cheers.
Julien (French)

2007/6/23, Nathan Nobbe <[EMAIL PROTECTED]>:


> On 6/23/07, Robert Cummings < [EMAIL PROTECTED]> wrote:
> Regardless of additional documentation or not, I think it's rather poor
> choice of programming style to mix the foreach construct with the older,
> lower level, internal array manipulation and probing functions. I think
> that is what should be documented since you just might get weird
> results :)

i agree; at least i have never had a need to determine the current index
of the internal array pointer in nearly 3 years working w/ php.
although it is somewhat interesting to experiment w/ the language to see
how it behaves :)

-nathan


On 6/23/07, Robert Cummings < [EMAIL PROTECTED]> wrote:
>
> On Sat, 2007-06-23 at 15:15 -0400, Nathan Nobbe wrote:
> >
> > in summary, COW or not; i think the documentation could be revised a
> bit to
> > clarify these subtleties.
>
> Regardless of additional documentation or not, I think it's rather poor
> choice of programming style to mix the foreach construct with the older,
> lower level, internal array manipulation and probing functions. I think
> that is what should be documented since you just might get weird
> results :)
>
> Cheers,
> Rob.
> --
> ..
> | InterJinn Application Framework - http://www.interjinn.com |
> ::
> | An application and templating framework for PHP. Boasting  |
> | a powerful, scalable system for accessing system services  |
> | such as forms, properties, sessions, and caches. InterJinn |
> | also provides an extremely flexible architecture for   |
> | creating re-usable components quickly and easily.  |
> `'
>
>



Re: [PHP] foreach() using current() strange beahvior

2007-06-23 Thread Nathan Nobbe

On 6/23/07, Robert Cummings <[EMAIL PROTECTED]> wrote:
Regardless of additional documentation or not, I think it's rather poor
choice of programming style to mix the foreach construct with the older,
lower level, internal array manipulation and probing functions. I think
that is what should be documented since you just might get weird
results :)


i agree; at least i have never had a need to determine the current index of
the internal array pointer in nearly 3 years working w/ php.
although it is somewhat interesting to experiment w/ the language to see how
it behaves :)

-nathan


On 6/23/07, Robert Cummings <[EMAIL PROTECTED]> wrote:


On Sat, 2007-06-23 at 15:15 -0400, Nathan Nobbe wrote:
>
> in summary, COW or not; i think the documentation could be revised a bit
to
> clarify these subtleties.

Regardless of additional documentation or not, I think it's rather poor
choice of programming style to mix the foreach construct with the older,
lower level, internal array manipulation and probing functions. I think
that is what should be documented since you just might get weird
results :)

Cheers,
Rob.
--
..
| InterJinn Application Framework - http://www.interjinn.com |
::
| An application and templating framework for PHP. Boasting  |
| a powerful, scalable system for accessing system services  |
| such as forms, properties, sessions, and caches. InterJinn |
| also provides an extremely flexible architecture for   |
| creating re-usable components quickly and easily.  |
`'




Re: [PHP] foreach() using current() strange beahvior

2007-06-23 Thread Robert Cummings
On Sat, 2007-06-23 at 15:15 -0400, Nathan Nobbe wrote:
>
> in summary, COW or not; i think the documentation could be revised a bit to
> clarify these subtleties.

Regardless of additional documentation or not, I think it's rather poor
choice of programming style to mix the foreach construct with the older,
lower level, internal array manipulation and probing functions. I think
that is what should be documented since you just might get weird
results :)

Cheers,
Rob.
-- 
..
| InterJinn Application Framework - http://www.interjinn.com |
::
| An application and templating framework for PHP. Boasting  |
| a powerful, scalable system for accessing system services  |
| such as forms, properties, sessions, and caches. InterJinn |
| also provides an extremely flexible architecture for   |
| creating re-usable components quickly and easily.  |
`'

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



Re: [PHP] foreach() using current() strange beahvior

2007-06-23 Thread Nathan Nobbe

Julien,

i reproduced your experiment and got a different result on the first one.  i
found that the internal pointer does not seem to be affected if there is a
check on the index of the internal pointer during iteration, but if there is
no check on the index during iteration the
pointer seems to get incremented.  needless to say this is rather strange. *
*also *turadg at berkeley dot edu* describes his experience w/ this issue on
the foreach 
documentationin
the user comments section.  he found that by aliasing the original
array
variable the behavior described in the documentation is realized.
i have summarized these findings in the following code segment, which you
can run yourself as well for corroboration

 $v) {
if(current($a) != false) {
echo current($a) . PHP_EOL;
} else {
var_dump(current($a));
}
}
/// check the internal pointer after iteration is complete (should be
pointing at last index)
if(current($a) != false) { // strangely this is still the first index of the
array
echo current($a) . PHP_EOL;
} else {
var_dump(current($a));
}

echo 'experiment 1b.' . PHP_EOL;
/// another run through the array where there is no check on the value of
the internal pointer during each iteration
foreach($a as $k => $v) {}
/// check the internal pointer after iteration this time
if(current($a) != false) { // and now the pointer is the last index of the
array (as expected)
echo current($a) . PHP_EOL;
} else {
var_dump(current($a));
}

echo 'experiment 2a.' . PHP_EOL;
 ALIAS THE ORIGINAL ARRAY VARIABLE
$a2 =& $a; // create an alias of $a for further experimentation
foreach($a as $k => $v) { // first experiment
if(current($a) != false) { // now the internal index is being incremented
echo current($a) . PHP_EOL;
} else {
var_dump(current($a));
}
}

if(current($a) != false) { // and here the internal pointer is the last
index
echo current($a) . PHP_EOL;
} else {
var_dump(current($a));
}

echo 'experiment 2b.' . PHP_EOL;
/// second experiment (no checking of the index during iteration)
foreach($a as $k => $v) {}
if(current($a) != false) { // and the internal pointer is the last index
echo current($a) . PHP_EOL;
} else {
var_dump(current($a));
}
?>

/// this is the output on my machine
experiment 1a.
one
one
one
one
experiment 1b.
bool(false)
experiment 2a.
two
three
bool(false)
bool(false)
experiment 2b.
bool(false)

in summary, COW or not; i think the documentation could be revised a bit to
clarify these subtleties.

-nathan


On 6/23/07, Julien Pauli <[EMAIL PROTECTED]> wrote:


Please consider this code :

$v) {
}

var_dump(current($a));
// outputs boll(false);

that's expected as foreach moves the internal array pointer, it's
documented.

now consider this :

$v) {
current($a);
}

var_dump(current($a));
// outputs string("One");

When using the internal pointer just by calling current() (so not moving
it), the output of the foreach loop has changed ...
Can someone explain that ?

regards.



Re: [PHP] foreach() using current() strange beahvior

2007-06-23 Thread Robert Cummings
On Sat, 2007-06-23 at 19:15 +0200, Julien Pauli wrote:
> Please consider this code :
> 
>  $a = array("One","Two","Three");
> 
> foreach ($a AS $k=>$v) {
> }
> 
> var_dump(current($a));
> // outputs boll(false);
> 
> that's expected as foreach moves the internal array pointer, it's
> documented.
> 
> now consider this :
> 
>  $a = array("One","Two","Three");
> 
> foreach ($a AS $k=>$v) {
> current($a);
> }
> 
> var_dump(current($a));
> // outputs string("One");
> 
> When using the internal pointer just by calling current() (so not moving
> it), the output of the foreach loop has changed ...
> Can someone explain that ?

The answers lies in the following although it's not terribly clear why
the behaviour is as it is:


Note: Unless the array is referenced, foreach operates on a copy of the
specified array and not the array itself. Therefore, the array pointer
is not modified as with the each() construct, and changes to the array
element returned are not reflected in the original array. However, the
internal pointer of the original array is advanced with the processing
of the array. Assuming the foreach loop runs to completion, the array's
internal pointer will be at the end of the array.


If you understand how PHP copies values then it makes sense. Let me
explain... When the foreach loop is entered $a is copied for use by the
foreach itrator; however, a copy in PHP is a lazy copy. This means that
the the copy is still referencing the original value, and this is why
the internal pointer is still advanced.

Now what probably happens is that when the current() function is used on
$a something internally tells the PHP engine that a modification has
occurred, as such the COW (copy on write) policy comes into effect. This
essentially differentiates a copy since a change is occurring such that
there is now a real and distinct copy. So internally $a had the internal
pointer reset on entry to the foreach loop, current() somehow invokes
the COW policy causing a real copy to be generated, and then the foreach
continues merrily forward with the real copy leaving current() to work
with the original copy. Hope that make sense to you :)

For what it's worth, COW is why if you have a variable consuming 100
megabytes stored in $x and you assign it to $y that you don't end up
consuming 200 megs of memory. Now if $x is a string and you change
append one character to $y, you should find that now you are consuming
200 megs of memory since a real copy is generated when the change is
incurred. This is an optimization strategy.

Cheers,
Rob.
-- 
..
| InterJinn Application Framework - http://www.interjinn.com |
::
| An application and templating framework for PHP. Boasting  |
| a powerful, scalable system for accessing system services  |
| such as forms, properties, sessions, and caches. InterJinn |
| also provides an extremely flexible architecture for   |
| creating re-usable components quickly and easily.  |
`'

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



[PHP] foreach() using current() strange beahvior

2007-06-23 Thread Julien Pauli

Please consider this code :

$v) {
}

var_dump(current($a));
// outputs boll(false);

that's expected as foreach moves the internal array pointer, it's
documented.

now consider this :

$v) {
current($a);
}

var_dump(current($a));
// outputs string("One");

When using the internal pointer just by calling current() (so not moving
it), the output of the foreach loop has changed ...
Can someone explain that ?

regards.