Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.php > #5315 > unrolled thread
| Started by | "Leonardo Azpurua" <leonardo@exmvps.org> |
|---|---|
| First post | 2012-04-02 11:47 -0430 |
| Last post | 2012-04-04 10:48 +0200 |
| Articles | 6 — 4 participants |
Back to article view | Back to comp.lang.php
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
| From | "Leonardo Azpurua" <leonardo@exmvps.org> |
|---|---|
| Date | 2012-04-02 11:47 -0430 |
| Subject | Doubt 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]
| From | "Álvaro G. Vicario" <alvaro.NOSPAMTHANX@demogracia.com.invalid> |
|---|---|
| Date | 2012-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]
| From | "M. Strobel" <sorry_no_mail_here@nowhere.dee> |
|---|---|
| Date | 2012-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]
| From | Jerry Stuckle <jstucklex@attglobal.net> |
|---|---|
| Date | 2012-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]
| From | "M. Strobel" <sorry_no_mail_here@nowhere.dee> |
|---|---|
| Date | 2012-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]
| From | "M. Strobel" <sorry_no_mail_here@nowhere.dee> |
|---|---|
| Date | 2012-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