FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » Imported messages » comp.lang.php » Doubt regarding an array of references...
Show: Today's Messages :: Unread Messages :: Show Polls :: Message Navigator
| Subscribe to topic | Bookmark topic 
Switch to threaded view of this topic Create a new topic Submit Reply
Doubt regarding an array of references... [message #177493] Mon, 02 April 2012 12:17 Go to next message
Leonardo Azpurua is currently offline  Leonardo Azpurua
Messages: 46
Registered: December 2010
Karma: 0
Member
add to buddy list
ignore all messages by this user
Hi,

I am coding a simple parser, where a construct is made of a fixed number
sequence of varIDs or quoted literals that may or may not be separated by
punctuators.

In order to avoid a repetition of similar statements, I decided to try if I
could store the references of the variables where each value should be
stored and then perform a loop in order to extract and store the symbols.

The try was this little program:

$a = $b = $c = "nil";
echo "a = $a, b = $b, c = $c<br>\n";

$d = array(&$a, &$b, &$c);
for ($n = 0; $n < count($d); $n++) $d[$n] = $n;
echo "a = $a, b = $b, c = $c<br>\n";

for ($n = 0; $n < count($d); $n++) $d[$n] = ($n + 100);
echo "a = $a, b = $b, c = $c<br>\n";

$n = 200;
foreach ($d as &$nx) $nx = $n++;; // why &$nx ?
echo "a = $a, b = $b, c = $c<br>\n";

The output is this:

a = nil, b = nil, c = nil
a = 0, b = 1, c = 2
a = 100, b = 101, c = 102
a = 200, b = 201, c = 202

so it works as needed.

My question is regarding the instruction with the comment.

My first try was to write foreach ($d as $nx), since each element in the $d
array is supposed to be already holding a reference.

I find this confusing. Wouldn't &$nx holde the reference to the array
element, instead of the reference contained within the array element?

Thanks in advance.

--
Re: Doubt regarding an array of references... [message #177507 is a reply to message #177493] Tue, 03 April 2012 05:02 Go to previous messageGo to next message
alvaro.NOSPAMTHANX is currently offline  alvaro.NOSPAMTHANX
Messages: 277
Registered: September 2010
Karma: 0
Senior Member
add to buddy list
ignore all messages by this user
El 02/04/2012 18:17, Leonardo Azpurua escribió/wrote:
> I am coding a simple parser, where a construct is made of a fixed number
> sequence of varIDs or quoted literals that may or may not be separated by
> punctuators.
>
> In order to avoid a repetition of similar statements, I decided to try if I
> could store the references of the variables where each value should be
> stored and then perform a loop in order to extract and store the symbols.
>
> The try was this little program:

As a general rule, I suggest you debug with var_dump(). Plain echos cast
everything to string and hide most of the subtleties you are interested
in when debugging.

>
> $a = $b = $c = "nil";
> echo "a = $a, b = $b, c = $c<br>\n";
>
> $d = array(&$a,&$b,&$c);
> for ($n = 0; $n< count($d); $n++) $d[$n] = $n;
> echo "a = $a, b = $b, c = $c<br>\n";
>
> for ($n = 0; $n< count($d); $n++) $d[$n] = ($n + 100);
> echo "a = $a, b = $b, c = $c<br>\n";
>
> $n = 200;
> foreach ($d as&$nx) $nx = $n++;; // why&$nx ?

Why «&$nx»? Because the foreach() construct does not create references
by itself. This:

foreach($foo as $bar){
$bar = 'New value';
}

.... is roughly equivalent to:

for($i=0; $i<count($foo); $i++){
$bar = $foo[$i]; // Good old copy, not reference
$bar = 'New value'; // $foo[$i] keeps old value
}

(Please note we are talking about arrays and scalars; PHP objects follow
their own rules).

> echo "a = $a, b = $b, c = $c<br>\n";

Last but not least, an additional important bit -- Every time you use
references in a foreach() construct, don't forget to unset the temporary
variable. Otherwise, you'll face unexpected side effects if you use the
same variable name in another loop. Run and compare this:

$foo = range(1, 10);
foreach($foo as &$bar){
$bar *= 100;
}

var_dump($foo);
foreach($foo as $bar){
}
var_dump($foo);

.... and this:

$foo = range(1, 10);
foreach($foo as &$bar){
$bar *= 100;
}
unset($bar); // <--

var_dump($foo);
foreach($foo as $bar){
}
var_dump($foo);

(In case you didn't see it, there's a full chapter dedicated to
references [1])

[1] http://www.php.net/manual/en/language.references.php



--
-- http://alvaro.es - Álvaro G. Vicario - Burgos, Spain
-- Mi sitio sobre programación web: http://borrame.com
-- Mi web de humor satinado: http://www.demogracia.com
--
Re: Doubt regarding an array of references... [message #177508 is a reply to message #177507] Tue, 03 April 2012 07:39 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
add to buddy list
ignore all messages by this user
Am 03.04.2012 11:02, schrieb "Álvaro G. Vicario":
> El 02/04/2012 18:17, Leonardo Azpurua escribió/wrote:
>> I am coding a simple parser, where a construct is made of a fixed number
>> sequence of varIDs or quoted literals that may or may not be separated by
>> punctuators.
>>
>> In order to avoid a repetition of similar statements, I decided to try if I
>> could store the references of the variables where each value should be
>> stored and then perform a loop in order to extract and store the symbols.
>>
>> The try was this little program:
>
> As a general rule, I suggest you debug with var_dump(). Plain echos cast everything
> to string and hide most of the subtleties you are interested in when debugging.
>
>>
>> $a = $b = $c = "nil";
>> echo "a = $a, b = $b, c = $c<br>\n";
>>
>> $d = array(&$a,&$b,&$c);
>> for ($n = 0; $n< count($d); $n++) $d[$n] = $n;
>> echo "a = $a, b = $b, c = $c<br>\n";
>>
>> for ($n = 0; $n< count($d); $n++) $d[$n] = ($n + 100);
>> echo "a = $a, b = $b, c = $c<br>\n";
>>
>> $n = 200;
>> foreach ($d as&$nx) $nx = $n++;; // why&$nx ?
>
> Why «&$nx»? Because the foreach() construct does not create references by itself. This:
>
> foreach($foo as $bar){
> $bar = 'New value';
> }
>
> ... is roughly equivalent to:
>
> for($i=0; $i<count($foo); $i++){
> $bar = $foo[$i]; // Good old copy, not reference
> $bar = 'New value'; // $foo[$i] keeps old value
> }
>
> (Please note we are talking about arrays and scalars; PHP objects follow their own
> rules).
>
>> echo "a = $a, b = $b, c = $c<br>\n";
>
> Last but not least, an additional important bit -- Every time you use references in a
> foreach() construct, don't forget to unset the temporary variable. Otherwise, you'll
> face unexpected side effects if you use the same variable name in another loop. Run
> and compare this:
>
> $foo = range(1, 10);
> foreach($foo as &$bar){
> $bar *= 100;
> }
>
> var_dump($foo);
> foreach($foo as $bar){
> }
> var_dump($foo);
>
> ... and this:
>
> $foo = range(1, 10);
> foreach($foo as &$bar){
> $bar *= 100;
> }
> unset($bar); // <--
>
> var_dump($foo);
> foreach($foo as $bar){
> }
> var_dump($foo);
>
> (In case you didn't see it, there's a full chapter dedicated to references [1])
>
> [1] http://www.php.net/manual/en/language.references.php

My 2¢:

The problem with the counted for-loop is tedious writing, and off-by-one error.

The problem with the foreach-loop is: don't forget to use the key when you want to
change values!

This works:

#--------------------------------
strobel@s114-intel:~> php -a
Interactive shell

php > $a = array(1,2,3);
php > foreach ($a as $k=>$v) { $a[$k]++; }
php > var_dump($a);
array(3) {
[0]=>
int(2)
[1]=>
int(3)
[2]=>
int(4)
}
php > foreach ($a as $k=>$v) { $a[$k]*=4; }
php > var_dump($a);
array(3) {
[0]=>
int(8)
[1]=>
int(12)
[2]=>
int(16)
}
php >
#--------------------------

I see references in PHP as "a can of worms", in PHP5 they are only necessary in very
special cases.

/Str.
Re: Doubt regarding an array of references... [message #177509 is a reply to message #177508] Tue, 03 April 2012 08:03 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
add to buddy list
ignore all messages by this user
On 4/3/2012 7:39 AM, M. Strobel wrote:
>
> My 2¢:
>
> The problem with the counted for-loop is tedious writing, and off-by-one error.
>

No error if you remember what you're doing. They can be tedious, but
allow more control over the loop. The real problem here is the indicies
must be integers and sequential.

OTOH, foreach() loops process the elements in the order they were added
to the array, which is not necessarily numeric order, i.e.

$a = array(3=>4, 2=>5, 1=>6);
foreach ($a as $v)
echo "$v\n";

prints
4
5
6

Whereas
for ($i = 1; i < 4; i++)
echo "$v\n";

prints
6
4
5

> The problem with the foreach-loop is: don't forget to use the key when you want to
> change values!
>
> This works:
>
> #--------------------------------
> strobel@s114-intel:~> php -a
> Interactive shell
>
> php> $a = array(1,2,3);
> php> foreach ($a as $k=>$v) { $a[$k]++; }
> php> var_dump($a);
> array(3) {
> [0]=>
> int(2)
> [1]=>
> int(3)
> [2]=>
> int(4)
> }
> php> foreach ($a as $k=>$v) { $a[$k]*=4; }
> php> var_dump($a);
> array(3) {
> [0]=>
> int(8)
> [1]=>
> int(12)
> [2]=>
> int(16)
> }
> php>
> #--------------------------
>
> I see references in PHP as "a can of worms", in PHP5 they are only necessary in very
> special cases.
>
> /Str.
>

References are very handy - and prevent the need for such gyrations as
you're going through.

I find this much easier to understand:

$a = array(1,2,3);
foreach ($a as &$v) {
$v++;
}


--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: Doubt regarding an array of references... [message #177510 is a reply to message #177509] Tue, 03 April 2012 08:15 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
add to buddy list
ignore all messages by this user
Am 03.04.2012 14:03, schrieb Jerry Stuckle:
> On 4/3/2012 7:39 AM, M. Strobel wrote:
>>
>> My 2¢:
>>
>> The problem with the counted for-loop is tedious writing, and off-by-one error.
>>
>
> No error if you remember what you're doing. They can be tedious, but allow more
> control over the loop. The real problem here is the indicies must be integers and
> sequential.
>
> OTOH, foreach() loops process the elements in the order they were added to the array,
> which is not necessarily numeric order, i.e.

Very true, and very apparent when you mix numeric and alphanumeric keys. For me this
is a feature.

>
>> The problem with the foreach-loop is: don't forget to use the key when you want to
>> change values!
>>
>> This works:
>>
>> #--------------------------------
>> strobel@s114-intel:~> php -a
>> Interactive shell
>>
>> php> $a = array(1,2,3);
>> php> foreach ($a as $k=>$v) { $a[$k]++; }
>> php> var_dump($a);
>> array(3) {
>> [0]=>
>> int(2)
>> [1]=>
>> int(3)
>> [2]=>
>> int(4)
>> }
--cut--
>>
>> I see references in PHP as "a can of worms", in PHP5 they are only necessary in very
>> special cases.
>>
>> /Str.
>>
>
> References are very handy - and prevent the need for such gyrations as you're going
> through.
>
> I find this much easier to understand:
>
> $a = array(1,2,3);
> foreach ($a as &$v) {
> $v++;
> }

Yeah, this looks clear to me. Anyway I would advice any beginner to stay away from
references in the first place.

Especially with all this old PHP4 code in the wild you get on the wrong track.

/Str.
Re: Doubt regarding an array of references... [message #177515 is a reply to message #177509] Wed, 04 April 2012 04:48 Go to previous message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
add to buddy list
ignore all messages by this user
Am 03.04.2012 14:03, schrieb Jerry Stuckle:
> On 4/3/2012 7:39 AM, M. Strobel wrote:
>>
>> My 2¢:
>>
>> The problem with the counted for-loop is tedious writing, and off-by-one error.
>>
>
> No error if you remember what you're doing. They can be tedious, but allow more
> control over the loop. The real problem here is the indicies must be integers and
> sequential.
>
> OTOH, foreach() loops process the elements in the order they were added to the array,
> which is not necessarily numeric order, i.e.
>
> $a = array(3=>4, 2=>5, 1=>6);
> foreach ($a as $v)
> echo "$v\n";
>
> prints
> 4
> 5
> 6
>
> Whereas
> for ($i = 1; i < 4; i++)
> echo "$v\n";
>
> prints
> 6
> 4
> 5
>
>> The problem with the foreach-loop is: don't forget to use the key when you want to
>> change values!
>>
>> This works:
>>
>> #--------------------------------
>> strobel@s114-intel:~> php -a
>> Interactive shell
>>
>> php> $a = array(1,2,3);
>> php> foreach ($a as $k=>$v) { $a[$k]++; }
>> php> var_dump($a);
>> array(3) {
>> [0]=>
>> int(2)
>> [1]=>
>> int(3)
>> [2]=>
>> int(4)
>> }
>> php> foreach ($a as $k=>$v) { $a[$k]*=4; }
>> php> var_dump($a);
>> array(3) {
>> [0]=>
>> int(8)
>> [1]=>
>> int(12)
>> [2]=>
>> int(16)
>> }
>> php>
>> #--------------------------
>>
>> I see references in PHP as "a can of worms", in PHP5 they are only necessary in very
>> special cases.
>>
>> /Str.
>>
>
> References are very handy - and prevent the need for such gyrations as you're going
> through.
>
> I find this much easier to understand:
>
> $a = array(1,2,3);
> foreach ($a as &$v) {
> $v++;
> }
>

more comments:

I wondered if your version is faster. It is a little slower:

Records read: 3.917.116, in seconds: 4.1342887878418
histogram_foreach in seconds: 1.2060449123383 "foreach ($a as $k=>$v)"
histogram_arraywalk in seconds: 2.3749718666077
histogram_whileeach in seconds: 2.9545080661774
histogram_foreach_r in seconds: 1.5193150043488 "foreach ($a as &$v)"

I am careful with generalizing benchmark results, this at least shows my "plain"
version has no performance penalty.

Anyway, my advice is: optimize for clearness && cleannes of code first.

/Str.
Quick Reply
Formatting Tools:   
  Switch to threaded view of this topic Create a new topic
Previous Topic: A little tip
Next Topic: How to etablish an SSH2 tunnel with php ?
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Tue Oct 24 07:34:31 EDT 2017

Total time taken to generate the page: 0.00749 seconds