Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.php > #5315 > unrolled thread

Doubt regarding an array of references...

Started by"Leonardo Azpurua" <leonardo@exmvps.org>
First post2012-04-02 11:47 -0430
Last post2012-04-04 10:48 +0200
Articles 6 — 4 participants

Back to article view | Back to comp.lang.php


Contents

  Doubt regarding an array of references... "Leonardo Azpurua" <leonardo@exmvps.org> - 2012-04-02 11:47 -0430
    Re: Doubt regarding an array of references... "Álvaro G. Vicario" <alvaro.NOSPAMTHANX@demogracia.com.invalid> - 2012-04-03 11:02 +0200
      Re: Doubt regarding an array of references... "M. Strobel" <sorry_no_mail_here@nowhere.dee> - 2012-04-03 13:39 +0200
        Re: Doubt regarding an array of references... Jerry Stuckle <jstucklex@attglobal.net> - 2012-04-03 08:03 -0400
          Re: Doubt regarding an array of references... "M. Strobel" <sorry_no_mail_here@nowhere.dee> - 2012-04-03 14:15 +0200
          Re: Doubt regarding an array of references... "M. Strobel" <sorry_no_mail_here@nowhere.dee> - 2012-04-04 10:48 +0200

#5315 — Doubt regarding an array of references...

From"Leonardo Azpurua" <leonardo@exmvps.org>
Date2012-04-02 11:47 -0430
SubjectDoubt regarding an array of references...
Message-ID<jlcjem$rrb$1@dont-email.me>
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.

--

[toc] | [next] | [standalone]


#5334

From"Álvaro G. Vicario" <alvaro.NOSPAMTHANX@demogracia.com.invalid>
Date2012-04-03 11:02 +0200
Message-ID<jleeb1$a6i$1@dont-email.me>
In reply to#5315
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
--

[toc] | [prev] | [next] | [standalone]


#5335

From"M. Strobel" <sorry_no_mail_here@nowhere.dee>
Date2012-04-03 13:39 +0200
Message-ID<9u05rvFhmrU1@mid.uni-berlin.de>
In reply to#5334
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.

[toc] | [prev] | [next] | [standalone]


#5336

FromJerry Stuckle <jstucklex@attglobal.net>
Date2012-04-03 08:03 -0400
Message-ID<jleov5$9la$1@dont-email.me>
In reply to#5335
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@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#5337

From"M. Strobel" <sorry_no_mail_here@nowhere.dee>
Date2012-04-03 14:15 +0200
Message-ID<9u07vpF25hU1@mid.uni-berlin.de>
In reply to#5336
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.

[toc] | [prev] | [next] | [standalone]


#5342

From"M. Strobel" <sorry_no_mail_here@nowhere.dee>
Date2012-04-04 10:48 +0200
Message-ID<9u2g7aF5jgU1@mid.uni-berlin.de>
In reply to#5336
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.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.php


csiph-web