Vreemde programma constructie zonder return
Ik kwam bij het uitspitten van een PHP bibliotheek (meer bepaald de form_validation library van CodeIgniter 3.1.11, zie https://github.com/bcit-ci/CodeIgniter/blob/develop/system/libraries/Form_validation.php, lijn 493) volgende constructie tegen:
Ik snap niet wat deze lijn code doet (er wordt immers geen return gedaan van de conditie). Kan iemand mij hierbij helpen dit te interpreteren?
Bedankt!
Kurt
Edit:
UBB-tags gefixxed. Opmaakcodes werken hiet met blokhaken. Zie ook de Veelgestelde Vragen.
Gewijzigd op 18/10/2019 15:58:05 door - Ariën -
Het tweede deel van de && wordt nl. alleen uitgevoerd als de 1e true geeft.
Geen idee waarom dit zo "cryptisch" is gedaan. Misschien schrijft de coding standard accolades voor en had het danmoeten worden - en had de auteur geen zin in die 3 extra regels?
Volgens mij staat hier effectief gewoonGeen idee waarom dit zo "cryptisch" is gedaan. Misschien schrijft de coding standard accolades voor en had het danmoeten worden - en had de auteur geen zin in die 3 extra regels?
Gewijzigd op 18/10/2019 16:15:20 door Rob Doemaarwat
Stel dat je het predikaat (het Boolse statement) A && B hebt. Het resultaat van A && B is alleen true als beide delen, zowel A alsook B, true zijn. Bij lazy evaluation wordt in beginsel enkel het eerste deel geïnspecteerd. Immers, als A ongelijk is aan true (oftewel false), dan kan A && B nooit true opleveren en je hoeft dan dus B ook niet te inspecteren (of uit te voeren).
PHP valideert op deze manier Boolse statements. Het bovenstaande is equivalent aan:
In dit geval is het waarschijnlijk "gewoon" een verkorte schrijfwijze van het bovenstaande, maar je hebt interessantere toepassingen van lazy evaluation als de operaties mogelijk "duur" zijn. Je zou dan zoiets kunnen doen:
De <dure operatie> (CPU, geheugen) wordt dan niet uitgevoerd als <goedkope operatie> false teruggeeft.
Maar voor hetzelfde geld gebruik je dus een if-statement. Indien dan mogelijk is. De &&-constructie zou je bijvoorbeeld kunnen gebruiken in query-optimalisatie door de goedkope condities vooraan te zetten in je WHERE-statement.
Op eenzelfde wijze werkt lazy evaluation voor ||. Indien in A || B het eerste deel (A) true is, dan maakt het niet uit wat voor waarde B heeft, het resultaat is dan toch true, dus ook dan wordt B niet geïnspecteerd (noch uitgevoerd).
Gewijzigd op 18/10/2019 16:41:26 door Thomas van den Heuvel
Beste Rob, Thomas, bedankt voor jullie leerrijke reactie! Had ik nog nooit van gehoord...
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
31
32
33
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
31
32
33
<?php
// https://www.phphulp.nl/php/forum/topic/vreemde-programma-constructie-zonder-return/103138
function executeA($in) {
if ($in) {
echo 'A';
} else {
echo 'not A';
}
return $in;
}
function executeB($in) {
if ($in) {
echo 'B';
} else {
echo 'not B';
}
return $in;
}
$a = true;
$b = true;
executeA($a) && executeB($b); // levert AB
echo '<br>';
executeA($a) || executeB($b); // levert A - vanwege lazy evaluation, executeB() wordt niet uitgevoerd
echo '<br>';
$a = false;
executeA($a) && executeB($b); // levert not A - vanwege lazy evaluation, executeB() wordt niet uitgevoerd
echo '<br>';
executeA($a) || executeB($b); // levert not AB
?>
// https://www.phphulp.nl/php/forum/topic/vreemde-programma-constructie-zonder-return/103138
function executeA($in) {
if ($in) {
echo 'A';
} else {
echo 'not A';
}
return $in;
}
function executeB($in) {
if ($in) {
echo 'B';
} else {
echo 'not B';
}
return $in;
}
$a = true;
$b = true;
executeA($a) && executeB($b); // levert AB
echo '<br>';
executeA($a) || executeB($b); // levert A - vanwege lazy evaluation, executeB() wordt niet uitgevoerd
echo '<br>';
$a = false;
executeA($a) && executeB($b); // levert not A - vanwege lazy evaluation, executeB() wordt niet uitgevoerd
echo '<br>';
executeA($a) || executeB($b); // levert not AB
?>
Zo kom je soms ook van die rare if statements tegen:
Code (php)
Terwijl dit hetzelfde doet
Soms zit een programmeur ook even zonder koffie ;-)
Gewijzigd op 18/10/2019 17:55:41 door Frank Nietbelangrijk
Frank Nietbelangrijk op 18/10/2019 17:15:41:
Sja, maar dat soort fratsen kun je zelf makkelijk voorkomen door je te bedienen van simpele programmeerprincipes, zoals jij ook doet:
- het is vaak niet nodig om expliciet te vergelijken met Boolse waarde (=== true, === false)
- als je de conditieblokken kunt inverteren zodat je een negatie (!) kunt vermijden dan zou je dat moeten doen
Wat dat betreft is de "A && B" constructie nog redelijk clean, maar je moet wel weten wat voor implicaties dit heeft icm lazy evaluation.
Over die boolse waarden daar heeft ook iedere programmeur blijkbaar zijn eigen voorkeur in. Voor mij zou ook prima zijn. Wat wel een klein voordeel heeft is de true of false links in de conditie te plaatsen. Je krijgt dan een parse error als je per ongeluk een = (assignment) in plaats van een == of === gebruikt.
Wat mij betreft hebben functies/constructs die (vaak door naamgeving) al min of meer impliceren dat ze een Boolse waarde retourneren niet nog een expliciete vergelijking met een Boolean nodig, tenzij je maar één case hebt (en geen else-deel) die interessant is.
En in dat opzicht is het misschien ook weer beter om een expliciete vergelijking te doen met false in plaats van een negatie (!) ofzo. Een uitroepteken zie je snel(ler) over het hoofd.
Of wanneer return-values ten onrechte tot de verkeerde Boolse waarde kunnen evalueren (omdat PHP het niet zo nauw met types neemt) als dat niet de bedoeling is.
Er zijn altijd uitzonderingen op regels :).