php bug of mijn fout???
Code (php)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
$a = array(1,2,3,4,5,6);
foreach ($a as &$b) {
$b *=2;
}
foreach ($a as $b) {
echo $b . '<br>';
}
foreach ($a as &$b) {
$b *=2;
}
foreach ($a as $b) {
echo $b . '<br>';
}
output
2
4
6
8
10
10
verwacht
2
4
6
8
10
12
Waarom heb ik 2X 10 en niet 10 en 12
Doe ik iets fout of is dit een bug
Jan
Gewijzigd op 29/10/2019 13:16:25 door - Ariën -
Ik kom er ook niet uit;
Code (php)
Zoals ik het begrijp gaat alleen de laatste berekening niet goed.
Dit is mijn output
2
4
6
8
10
12
14
14
Gewijzigd op 29/10/2019 14:00:48 door Zwolly Wood
Het speelt wel in alle versies van PHP, dus het is geen tussentijdse bug.
Ik heb een bug gevonden :)
Na 10tallen in Excel en Windows nu eentje in php
Toevoeging op 29/10/2019 14:08:55:
Hoe kunnen we dit doorspelen?
Just interesting. Ik heb het ook even voorgelegd aan Tweakers. Toch benieuwd hoe dit zit. Op Linux speelt dit wel onder alle versies, waaronder de EOL.
Update: Ook op Windows speelt het.
"$b blijft een referentie naar het laatste element uit de eerste loop." zegt iemand daar.
unset($b); na je eerste foreach zou moeten helpen.
Toch zijn hulplijntjes wel eens handig :P
En ja, PHP blijft een 'dumb programmer language'
Gewijzigd op 29/10/2019 16:23:37 door - Ariën -
Dit werkt altijd, en maakt wat mij betreft expliciet duidelijk wat de bedoeling is:
Een callback- of lambda-functie doet het ook prima:
Daarbij, als je dan toch volhardt in een aanpak met een referentie, dan loont het op zijn minst de moeite om er in commentaar bij te vermelden wat het eigenlijk zou moeten doen. Als dit dan niet voldoet aan de specificatie, dan weet je op zijn minst hoe je dit moet veranderen. Dit verdient ook in algemene zin de voorkeur. Het kan je later helpen om de draad weer op te pakken als je de code een tijd niet gezien hebt.
Het probleem is dus overigens niet $a. De waarden in $a bevatten na afloop van de eerste foreach-loop de correcte waarden. Het is die $b, die je gebruikt om in de tweede loop $a te dumpen. Die, zoals in die Tweakers discussie wordt aangehaald, blijft bestaan buiten de scope van de eerste foreach-loop. Niet helemaal netjes, maar soit. Op het moment dat je referenties gaat gebruiken moet je gewoon héél erg goed opletten.
Als je het volgende doet dan geeft dit gewoon het gewenste resultaat:
Code (php)
- Ariën - op 29/10/2019 16:10:33:
En ja, PHP blijft een 'dumb programmer language'
Nou nee, het zijn toch voornamelijk dumb programmers. PHP heeft nou eenmaal een aantal quirks en is ook heel laagdrempelig en accepteert veel, heel veel. Daarom is het zaak dat dit gecompenseerd wordt door enige programmeerdiscipline die menig (beginnend) "programmeur" gewoon (nog) niet heeft.
Ik zou gewoon wegsturen van een oplossing met referenties als je deze niet nodig hebt. Omdat dit dus onvoorziene consequenties kan hebben maar ook omdat er gewoon andere constructies zijn die veel transparanter zijn dan wat hier gebeurt.
Gewijzigd op 29/10/2019 17:06:13 door Thomas van den Heuvel
Gewoon aanleren om na een foreach() met een referentie altijd een unset() te doen (net zoals na een haakje openen een haakje sluiten komt).
Of gewoon geen referenties gebruiken als je dit kunt vermijden.
Gewijzigd op 29/10/2019 20:33:59 door Thomas van den Heuvel
Thomas van den Heuvel op 29/10/2019 17:01:20:
Wat je hier allemaal aan het doen bent is toch redelijk onorthodox.
Je hebt ABSOLUUT gelijk :)
Dit was slechts een testje. Ik wist dat de ampersand werkte in functies. Ik wist echter niet dat dit kon in een foreach en plots kwam ik dit tegen in een ander topic.
Mijn bedoeling was dus ook om gewoon even te testen hoe dit werkte. Niet om te gebruiken. Normaal werk ik dus ook met de key over de echte array.
Soms zijn het de stomme testjes, of programmeurs, die fouten vinden.
Volgens mij is het sowieso een bug.
Toch allen bedankt voor de input en het mee testen.
Jan
Jan R op 30/10/2019 09:18:49:
Volgens mij is het sowieso een bug.
Volgens mij is het sowieso een bug.
Lees het gelinkte topic naar Tweakers eens? ;-)
Code (php)
je krijgt dan
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
array(6) {
[0]=>
int(2)
[1]=>
int(4)
[2]=>
int(6)
[3]=>
int(8)
[4]=>
int(10)
[5]=>
&int(2)
}
4
array(6) {
[0]=>
int(2)
[1]=>
int(4)
[2]=>
int(6)
[3]=>
int(8)
[4]=>
int(10)
[5]=>
&int(4)
}
array(6) {
[0]=>
int(2)
[1]=>
int(4)
[2]=>
int(6)
[3]=>
int(8)
[4]=>
int(10)
[5]=>
&int(2)
}
4
array(6) {
[0]=>
int(2)
[1]=>
int(4)
[2]=>
int(6)
[3]=>
int(8)
[4]=>
int(10)
[5]=>
&int(4)
}
etc
je ziet dat het laatste element steeds vervangen wordt door de nieuwe waarde die in $b geplaatst wordt.
Zie ook de & voor int.
Toevoeging op 31/10/2019 14:11:03:
conclusie: vermijd by-reference als het niet per se nodig is.
Gewijzigd op 01/11/2019 10:49:55 door Ivo P