Bonjour,
je programme en PHP 4.
Je me suis rendu compte d'un phénomène que je trouve anormal.
Dans cette ligne de code :
if( BDD::Requete($sql_actuellement, 'actuellement') || BDD::Requete($sql_prochainement, 'prochainement') )
Je m'attend à ce que la fonction Requete() de la classe BDD soit exécuté deux fois. Si l'un des deux appel retourne TRUE, le code situé dans le if doit être exécuté.
Malheureusement pour moi, PHP4 ne fonctionne pas comme ça.
Il va exécuter la première fonction et si elle retourne TRUE, il rentre directement dans le if sans se soucier de la deuxième exécution de la fonction.
J'ai cherché sur la documentation officiel ( www.php.net ) mais rien n'est dit à ce sujet.
Avez vous une suggestion pour que quelque soit le cas, les deux appels de fonction soient traité ?
Merci.
# Normal
Posté par Pascal Terjan (site web personnel) . Évalué à 3.
[^] # Re: Normal
Posté par TazForEver . Évalué à 2.
[^] # Re: Normal
Posté par Greg . Évalué à 1.
Ce qui constitue une optimisation...
[^] # Re: Normal
Posté par -=[ silmaril ]=- (site web personnel) . Évalué à 2.
Il n'y a pas d'optimisation la dedans, ni de d'implementation a definir pour chaque langage, c'est la definition du OU logique et tout le monde le comprend comme cela, que ce soit les hommes ou les machines (pour peu qu'on ai pris la peine d'en lire la definition).
[^] # Re: Normal
Posté par KiKouN . Évalué à 2.
Quand tu fais un +, tu évalue les deux opérandes puis tu les additionne.
Pour le OU, tu devrais faire pareil.
Or, comme la valeur de la première opérande peut suffir dans certain cas pour déterminer le résultat et que donc la valeur de la seconde ne sera pas déterminante, on optimise le traitement en n'évaluant pas la seconde opérande.
Maintenant, si tu a envie de te faire taper les doigts par ton prof de math...
Sinon, OU n'est pas une opérande dans notre context:
http://www.linuxfr-france.org.invalid/prj/jargonf/O/opeacrande.html(...)
[^] # Re: Normal
Posté par TImaniac (site web personnel) . Évalué à 3.
[^] # Re: Normal
Posté par gc (site web personnel) . Évalué à 2.
En l'occurrence, c'est plutôt le fait que le calcul de l'opérande droit n'est pas nécessaire à l'obtention du résultat du OU logique dans le ca où le calcul de l'opérande gauche a donné un résultat vrai.
D'ailleurs, essaie d'écrire une fonction qui réalise la même chose qu'un OU logique (ce comportement paresseux) : tu ne pourras pas (sauf à passer une fonction et l'éxecuter conditionnellement dans la fonction) car lorsque tu passes comme opérande (enfin, là, paramètres de la fonction) tes deux calculs ils seront effectués avant d'être passés à la fonction.
C'est donc une optimisation dans le langage.
[^] # Re: Normal
Posté par TImaniac (site web personnel) . Évalué à 2.
bah non justement, la doc de PHP est vraiment très vague et ne précise pas ce comportement. Ils croient sans doute que celà personne n'aura l'intention de créer un compilateur ou un interpréteur PHP... en tout cas c'est trop peu documenté le langage en soit.
[^] # Re: Normal
Posté par Gordon Shumway . Évalué à 1.
cependant en php il y a deux "ou" (et deux "et") : || et or.
si mes souvenirs sont bons avec or tous les opérandes sont évalués même si le premier est vrai.
mais je ne sais plus où j'ai vu ça... pas dans la doc visiblement. Sans doute dans un livre.
[^] # Re: Normal
Posté par gc (site web personnel) . Évalué à 3.
[gc@meuh /tmp] echo '<? function preda() { echo "in preda\n"; return true; } function predb() { echo "in predb\n"; } if (preda() or predb()) {} ?>' > t.php
[gc@meuh /tmp] php t.php
in preda
[gc@meuh /tmp] echo '<? function preda() { echo "in preda\n"; return true; } function predb() { echo "in predb\n"; } if (preda() || predb()) {} ?>' > t.php
[gc@meuh /tmp] php t.php
in preda
[gc@meuh /tmp]
[^] # Re: Normal
Posté par gc (site web personnel) . Évalué à 2.
Il faut bien comprendre que l'évaluation de la partie droite du "ou" logique n'est pas nécessaire au calcul de la valeur de vérité de la branche if, si la partie gauche est déjà vraie. Alors pourquoi le langage la ferait-elle ? Ce n'est ni normal ni logique. Il n'y a pas besoin de précision particulière dans la documentation de PHP pour cela.
On s'est trop éloigné de la programmation fonctionnelle pour avoir une compréhension intuitive du phénomène ici, qui devient un "problème". On se permet d'utiliser un prédicat qui aura en outre un effet de bord et on est triste que l'effet de bord ne soit pas obtenu alors que le prédicat n'était pas nécessaire au calcul du résultat de la valeur de vérité de la branche.
Le seul point de documentation qui pourrait être donné, c'est de savoir si c'est d'abord l'opérande gauche du "ou" ou l'opérande droite qui doit être évalué. Je me disais que j'avais vaguement souvenance que ocaml ou haskell évalue de droite à gauche mais ce n'est pas le cas pour ocaml en tous cas :
# let va = ref true;;
val va : bool ref = {contents = true}
# let preda () = print_string "in preda\n"; !va = true;;
val preda : unit -> bool = <fun>
# let predb () = print_string "in predb\n"; !va = true;;
val predb : unit -> bool = <fun>
# let _ = if (preda () or predb ()) then "yo" else "flute";;
in preda
- : string = "yo"
Je suis trop nul en haskell pour tester ce langage par contre...
[^] # Re: Normal
Posté par Jean-Baptiste Mayer . Évalué à 3.
Mieux encore: il change suivant que l'on soit en interprété (ocamlrun) ou en bytecode...
[^] # Re: Normal
Posté par gc (site web personnel) . Évalué à 3.
Je pense que tu confonds l'ordre d'évaluation d'une fonction (là tu as tout à fait raison) avec "or" qui n'est pas une fonction mais un builtin avec un comportement particulier.
[gc@meuh /tmp] ocamlopt t.ml && file a.out && ./a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.4.1, dynamically linked (uses shared libs), not stripped
preda or predb :
in preda
fonction avec preda predb en parametre :
in preda
in predb
[gc@meuh /tmp] ocamlc t.ml && file a.out && ./a.out
a.out: a /usr/bin/ocamlrun script text executable
preda or predb :
in preda
fonction avec preda predb en parametre :
in predb
in preda
Et au passage, d'ailleurs moi aussi je confondais et c'est de ça que je me souvenais vaguement quand je parlais d'un ordre inverse d'évaluation : il s'agit bien de ocaml mais du comportement en mode bytecode à l'appel de fonctions.
[^] # Re: Normal
Posté par CoinKoin . Évalué à 1.
Non, par exemple, dans le langage Ada, il est bien précisé que l'évaluation n'est jamais paresseuse.
De plus, dans certains langages (notamment Ada, et aussi Pascal, je crois), l'ordre d'évaluation des paramètres d'un "ou" (ou d'un "et") n'est pas nécessairement le même que celui dans lequel les paramêtres apparaissent dans le code.
Cela signifie en particulier que, dans ces langages, par suite d'effets de bords, certains programmes peuvent s'exécuter différemment selon le compilateur employé. La faute au programmeur, qui aurait dû y faire attention lui-même.
>Alors pourquoi le langage la ferait-elle ?
C'est une question de standard du langage. Si la norme précise que l'évaluation est paresseuse, c'est logique, à condition toutefois que cette norme précise aussi que les arguments d'un tel "ou" sont bien évalués dans leur ordre d'apparition (si la norme spécifie qu'il y a évaluation paresseuse, mais que l'ordre d'évaluation des arguments est indéterminé, attention aux surprises!)
En revanche, si elle précise que l'évaluation n'est jamais paresseuse, pas de problème (sauf effets de bords et évaluation désordonnée).
Manifestement, la norme de php4 est silencieuse à ce sujet, ce qui signifie que l'on ne peut rien prévoir à l'avance (l'évaluation peut être ou non paresseuse, être ou non ordonnée, etc...) .
Donc le comportement observé est bien L'UN des comportements possibles de ce code, mais pas le seul.
Cela dit, à mon avis, il serait préférable que la norme précise expressément que les caractères paresseux et ordonnés des évaluations logiques ne sont pas spécifiés, cela éviterait les embrouilles.
# Comportement normal
Posté par Laurent Go . Évalué à 2.
http://www.php.net/manual/fr/migration.booleval.php(...)
[^] # Re: Comportement normal
Posté par cam360 . Évalué à 1.
Pour ma part je ne vois pas où est les problème. Comme son nom l'indique le traitement est effectué si l'une ou l'autre des conditions est respectée. Donc si la première l'est pas besoin d'aller plus loin, on n'est pas dans le cas d'un ET.
Dans ce cas si est correcte on rentre dans le if.
Si ce n'est pas correct on lit la deuxième condition.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.