473,396 Members | 2,036 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

foreach loops are sooooo tricky.....

Just something I would like to share:

I just learned the hard way (2 days detective work on a bug) that foreach
loops are not at all like for loops, not intuitive at all. BEWARE: arrays
and matrices are sparse by design/definition in PHP.

I'm doing some matrix manipulation in a Finite Element program.
Translating Fortran to PHP, because hosters won't allow anything else
than PHP.
I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?
Check out this code:

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

/*
you would expect this to mirror the matrix about a diagonal from upper
left to lower right multiplying each coefficient by 2 on the way...
However, the foreach loop is tricky. */
foreach($k as $i=>& $_k)
foreach($_k as $j=>&$__k)
{
$__k *= 2;
if ($i != $j)
$k[$j][$i ] = $__k;
}

foreach($k as &$_k)
{
foreach($_k as &$__k)
echo " $__k ";
echo "<BR>";
}

echo "<BR>";

/* this is better: */

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

for ($i=1; $i <= 6; $i++)
for ($j=$i; $j<= 6; $j++)
if (isset($k[$i][$j]))
{
$k[$i][$j] *= 2 ;
if ($i != $j)
$k[$j][$i] = $k[$i][$j];
}
foreach($k as &$_k)
{
foreach($_k as &$__k)
echo " $__k ";
echo "<BR>";
}
echo "<BR";
/*
* and what about this:
*
*/
$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,6=>1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

for ($i=1; $i <= 6; $i++)
for ($j=$i; $j<= 6; $j++)
if (isset($k[$i][$j]))
{
$k[$i][$j] *= 2 ;
if ($i != $j)
$k[$j][$i] = $k[$i][$j];
}
foreach($k as &$_k)
{
foreach($_k as &$__k)
echo " $__k ";
echo "<BR>";
}
Dec 1 '07 #1
7 2250
Osiris wrote:
Just something I would like to share:

I just learned the hard way (2 days detective work on a bug) that foreach
loops are not at all like for loops, not intuitive at all. BEWARE: arrays
and matrices are sparse by design/definition in PHP.

I'm doing some matrix manipulation in a Finite Element program.
Translating Fortran to PHP, because hosters won't allow anything else
than PHP.
I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?
Check out this code:

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

/*
you would expect this to mirror the matrix about a diagonal from upper
left to lower right multiplying each coefficient by 2 on the way...
However, the foreach loop is tricky. */
foreach($k as $i=>& $_k)
foreach($_k as $j=>&$__k)
{
$__k *= 2;
if ($i != $j)
$k[$j][$i ] = $__k;
}

foreach($k as &$_k)
{
foreach($_k as &$__k)
echo " $__k ";
echo "<BR>";
}

echo "<BR>";

/* this is better: */

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

for ($i=1; $i <= 6; $i++)
for ($j=$i; $j<= 6; $j++)
if (isset($k[$i][$j]))
{
$k[$i][$j] *= 2 ;
if ($i != $j)
$k[$j][$i] = $k[$i][$j];
}
foreach($k as &$_k)
{
foreach($_k as &$__k)
echo " $__k ";
echo "<BR>";
}
echo "<BR";
/*
* and what about this:
*
*/
$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,6=>1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

for ($i=1; $i <= 6; $i++)
for ($j=$i; $j<= 6; $j++)
if (isset($k[$i][$j]))
{
$k[$i][$j] *= 2 ;
if ($i != $j)
$k[$j][$i] = $k[$i][$j];
}
foreach($k as &$_k)
{
foreach($_k as &$__k)
echo " $__k ";
echo "<BR>";
}
I find foreach loops to be quite intuitive. However, your FORTRAN
naming conventions make your code very hard to understand, and I don't
have the time to try to figure out what you're trying to do.

Try using some descriptive names for your variables. It will make your
code a lot easier to understand.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Dec 1 '07 #2
NC
On Dec 1, 6:20 am, Osiris <e...@hotmail.comwrote:
>
I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?
Highly unlikely... Given the PHP team's obsession with OOP, expecting
anything quant-friendly is an unrealistic hope. OOP and numerical
computing don't mix too well...

At the same time, we have to keep in mind that Fortran has been around
for 50 years now, so the code base created over all that time is
incredibly rich, especially when it comes to numerical stuff. At
some point, I needed a couple of statistical routines in PHP, so I
ended up porting them from Fortran code written circa 1970...

A possible way out would be to take "Numerical Recipes in C" (which is
a C clone of "Numerical Recipes in Fortran") and wrap those C
functions into a PHP extension, but it still wouldn't solve the
problem of availability on shared hosting...

Cheers,
NC
Dec 1 '07 #3
Osiris <et**@hotmail.comwrote:
..
>Just something I would like to share:

I just learned the hard way (2 days detective work on a bug) that foreach
loops are not at all like for loops, not intuitive at all. BEWARE: arrays
and matrices are sparse by design/definition in PHP.
That's true, but I don't think that's the problem here.
>I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?
I doubt it. That's simply not its problem domain.
>Check out this code:

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

/* you would expect this to mirror the matrix about a diagonal from upper
left to lower right multiplying each coefficient by 2 on the way...
However, the foreach loop is tricky. */
My guess is that it's not the foreach loop that is biting you, but rather
the references.
>foreach($k as $i=>& $_k)
foreach($_k as $j=>&$__k)
{
$__k *= 2;
if ($i != $j)
$k[$j][$i ] = $__k;
}
What does this produce for you? Does the next-to-the-last line really do
what you think? Is that making a copy of the value, or is it storing a
reference to the value? That is, won't $k[2][1] simply be a reference to
$k[1][2], and not a separate value?

My only convenient server runs PHP 4, which does not support the reference
notation. If I change your code to this, which I believe to be equivalent:

foreach($k as $i=$_k)
foreach($_k as $j=>$__k)
{
$__k *= 2;
$k[$i][$j] = $__k;
if ($i != $j)
$k[$j][$i ] = $__k;
}

the result is a 6x6 square array where every element is 2.
--
Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.
Dec 2 '07 #4
On Sat, 01 Dec 2007 09:36:47 -0500, Jerry Stuckle wrote:
Osiris wrote:
>Just something I would like to share:

I just learned the hard way (2 days detective work on a bug) that foreach
loops are not at all like for loops, not intuitive at all. BEWARE: arrays
and matrices are sparse by design/definition in PHP.

I'm doing some matrix manipulation in a Finite Element program.
Translating Fortran to PHP, because hosters won't allow anything else
than PHP.
I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?
Check out this code:

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

/*
>
I find foreach loops to be quite intuitive. However, your FORTRAN
naming conventions make your code very hard to understand, and I don't
have the time to try to figure out what you're trying to do.

Try using some descriptive names for your variables. It will make your
code a lot easier to understand.
There is nothing to describe , really... this example is just about a
general matrix with numbers to be mirrored.

The issue here is, that in a foreach loop you can inadvertedly enter extra
coefficients in the matrix, that are processed in a next iteration.
A for loop determins exactly which coefficients to process. A foreach loop
processes all that it encounters, new or old.
Mind you: I know what the problem is with the code. I did not say PHP was
in error, just that foreach-es are not alway what you EXPECT them to
be.
Dec 2 '07 #5
On Sun, 02 Dec 2007 00:53:06 +0000, Tim Roberts wrote:
Osiris <et**@hotmail.comwrote:
.
>>Just something I would like to share:

I just learned the hard way (2 days detective work on a bug) that foreach
loops are not at all like for loops, not intuitive at all. BEWARE: arrays
and matrices are sparse by design/definition in PHP.

That's true, but I don't think that's the problem here.
>>I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?

I doubt it. That's simply not its problem domain.
>>Check out this code:

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

/* you would expect this to mirror the matrix about a diagonal from upper
left to lower right multiplying each coefficient by 2 on the way...
However, the foreach loop is tricky. */

My guess is that it's not the foreach loop that is biting you, but rather
the references.
>>foreach($k as $i=>& $_k)
foreach($_k as $j=>&$__k)
{
$__k *= 2;
if ($i != $j)
$k[$j][$i ] = $__k;
}

What does this produce for you? Does the next-to-the-last line really do
what you think? Is that making a copy of the value, or is it storing a
reference to the value? That is, won't $k[2][1] simply be a reference to
$k[1][2], and not a separate value?
this works ok, so the referencing is not the problem:
<?php
$f = array(1=>array(5=>1,3=>2,8=>3),array(3=>2,4,5));
foreach($f as &$_f)
foreach($_f as &$__f)
echo $__f." ";
for ($i=1; $i <= 6; $i++)
{
for ($j=1; $j <= 6; $j++)
echo $k[$i][$j]." ";
echo "<BR>";
}

?>

The thing is, that while mirroring a coefficient, it may be processed
again in a next iteration.
At the start of the routine, there is an upper triangular matrix, but
next, some elements of the lower triangle are added, having BEEN doubled.
foreach apparently does a
complete search for new elements each loop. Correct , but it's a very
different mechanism than a for loop, which pinpoints each element to
process

Now for the even more weird thing:
running the above loops in eclipse debugger, I get this:
2 4 4 4 4 4
4 2 4 4 4 4
4 4 2 4 4 4
4 4 4 2 4 4
4 4 4 4 2 4
4 4 4 4 4 2

Running it in Firefox on my localhost (apache 2), i get this:

2 2 2 2 2 2
2 1 1 1 1 1
2 2 1 1 1 1
2 2 2 1 1 1
2 2 2 2 1 1
2 2 2 2 2 1
Dec 2 '07 #6
The issue is, that foreach loop process any element of a matrix that it
will encounter.
For loops only the indexed elements (i,j)
When mirroring the upper triangular matrix, I ADD elements.

But now for the really kinky thing: running the following routine on my
localhost(apache 2.2.3,PHP5), I get
2 2 2 2 2 2
2 1 1 1 1 1
2 2 1 1 1 1
2 2 2 1 1 1
2 2 2 2 1 1
2 2 2 2 2 1
Running it through the Eclipse PHP Zend debugger I get (which, in my
opinion, is right):
2 4 4 4 4 4
4 2 4 4 4 4
4 4 2 4 4 4
4 4 4 2 4 4
4 4 4 4 2 4
4 4 4 4 4 2

<?php
$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));
foreach($k as $i=>& $_k)
foreach($_k as $j=>&$__k)
{
$__k *= 2;
if ($i != $j)
$k[$j][$i ] = $__k;
}

for ($i=1; $i <= 6; $i++)
{
for ($j=1; $j <= 6; $j++)
echo $k[$i][$j]." ";
echo "<BR>";
}

?>

I make this a new thread, to get explanations.
Dec 2 '07 #7
Osiris wrote:
On Sat, 01 Dec 2007 09:36:47 -0500, Jerry Stuckle wrote:
>Osiris wrote:
>>Just something I would like to share:

I just learned the hard way (2 days detective work on a bug) that foreach
loops are not at all like for loops, not intuitive at all. BEWARE: arrays
and matrices are sparse by design/definition in PHP.

I'm doing some matrix manipulation in a Finite Element program.
Translating Fortran to PHP, because hosters won't allow anything else
than PHP.
I wish PHP would do array and matrix stuff like Fortran or C, btw.
Something for PHP 6 ?
Check out this code:

$k = array(1=>
array(1=>1,1,1,1,1,1),
array(2=>1,1,1,1,1),
array(3=>1,1,1,1),
array(4=>1,1,1),
array(5=>1,1),
array(6=>1));

/*
>I find foreach loops to be quite intuitive. However, your FORTRAN
naming conventions make your code very hard to understand, and I don't
have the time to try to figure out what you're trying to do.

Try using some descriptive names for your variables. It will make your
code a lot easier to understand.

There is nothing to describe , really... this example is just about a
general matrix with numbers to be mirrored.

The issue here is, that in a foreach loop you can inadvertedly enter extra
coefficients in the matrix, that are processed in a next iteration.
A for loop determins exactly which coefficients to process. A foreach loop
processes all that it encounters, new or old.
Mind you: I know what the problem is with the code. I did not say PHP was
in error, just that foreach-es are not alway what you EXPECT them to
be.
Well, a foreach loop is supposed to go through all of the elements. So
I would expect it to also process additional elements if you add them in
the loop.

However, if you add extra elements to an array, the for loop will also
process them, i.e.

$myArray[0] = 0;
for ($i=0; $i<count($myArray); $i++) {
$myArray[$i+1] = $i*2+2;
}

will run for a long time...

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
js*******@attglobal.net
==================
Dec 2 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Randell D. | last post by:
Folks, Ever since reading an interesting article in Linux Format on PHP whereby suggested code writing was made that could enhance performance on a server, I've started testing various bits of...
12
by: Patrick Russell | last post by:
I am trying to figure out why the code listed below works in php v4.3.0 but not in v4.3.10: $string = "Param1=Val1;Param2=Val2;Param3=Val3"; $exploded_string = explode(";",$string);...
7
by: Phil | last post by:
Hi, I read somewhere that the new version (v1.1) has improved the performance of 'foreach' over 'for'. Is that true? I did some measurements and I still think for has an upperhand... ? Phil
104
by: cody | last post by:
What about an enhancement of foreach loops which allows a syntax like that: foeach(int i in 1..10) { } // forward foeach(int i in 99..2) { } // backwards foeach(char c in 'a'..'z') { } // chars...
3
by: cody | last post by:
why foreach does always have to declare a new variable? I have to write foreach (int n in array){} but Iam not allowed to write: int n=0; foreach (n in array){}
77
by: Peter Olcott | last post by:
http://www.tommti-systems.de/go.html?http://www.tommti-systems.de/main-Dateien/reviews/languages/benchmarks.html The above link shows that C# is 450% slower on something as simple as a nested loop....
3
by: Akira | last post by:
I noticed that using foreach is much slower than using for-loop, so I want to change our current code from foreach to for-loop. But I can't figure out how. Could someone help me please? Current...
9
by: Nathan Sokalski | last post by:
I am trying to use the System.Array.ForEach method in VB.NET. The action that I want to perform on each of the Array values is: Private Function AddQuotes(ByVal value As String) As String Return...
2
by: fjm | last post by:
Hello everyone, I need some help and direction with this code. I am trying to have the same functionality that this forum has with regard to the allowable length of time the post (Or in my case,...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.