Re: foreach() using current() strange beahvior

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 2007-06-23 at 19:15 +0200, Julien Pauli wrote:
> Please consider this code :
> 
> <?php
> $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 :
> 
> <?php
> $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


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux