'AND' vs '&&' en tant qu'opérateur

298

J'ai une base de code où les développeurs ont décidé d'utiliser ANDet ORau lieu de &&et ||.

Je sais qu'il y a une différence dans la priorité des opérateurs ( &&va avant and), mais avec le cadre donné ( PrestaShop pour être précis) ce n'est clairement pas une raison.

Quelle version utilisez-vous? Est andplus lisible que &&? Ou n'y a-t-il aucune différence?

ts.
la source
1
Notez qu'il ~s'agit de l'opérateur NOT au niveau du bit et non de la logique. ;-)
Gumbo
2
Oui je sais. Mauvaises habitudes :) . Il est un peu étrange qu'en PHP il y ait 'et', 'ou' et 'xor', mais il n'y a pas de 'non', n'est-ce pas?
ts.
1
@ts: la bonne réponse ici est celle fournie par R. Bemrose stackoverflow.com/questions/2803321/and-vs-as-operator/…
Marco Demaio
4
! est l'opérateur logique non
Razor Storm
2
@chiliNUT tout à fait raison. À l'époque, cela devait avoir du sens. Il semble que la réponse incorrecte cachée ait été punie à ce stade :)
doublejosh

Réponses:

664

Si vous utilisez ANDet OR, vous finirez par vous faire tromper par quelque chose comme ceci:

$this_one = true;
$that = false;

$truthiness = $this_one and $that;

Vous voulez deviner ce qui $truthinessest égal?

Si vous avez dit false... bzzzt, désolé, faux!

$truthinessci-dessus a la valeur true. Pourquoi? =a une priorité plus élevée que and. L'ajout de parenthèses pour montrer l'ordre implicite rend cela plus clair:

($truthiness = $this_one) and $that

Si vous l'avez utilisé à la &&place de anddans le premier exemple de code, cela fonctionnerait comme prévu et le serait false.

Comme indiqué dans les commentaires ci-dessous, cela fonctionne également pour obtenir la valeur correcte, car les parenthèses ont une priorité plus élevée que =:

$truthiness = ($this_one and $that)
Powerlord
la source
135
+1: cela doit être clairement exprimé dans la documentation PHP, ou PHP doit changer et donner la même priorité à ces opérateurs ou DEPRECATE and orune fois pour toutes. J'ai vu trop de gens penser qu'ils étaient exactement la même chose et les réponses ici sont plus de témoignages.
Marco Demaio
11
En fait, d'autres langages (par exemple, Perl et Ruby) ont également ces variantes avec la même distinction de priorité, il ne serait donc pas judicieux de s'écarter de cette norme (même si cela peut être déroutant pour les débutants) en rendant la priorité égale en PHP. Sans parler de la rétrocompatibilité de tonnes d'applications PHP.
Mladen Jablanović
23
L'incapacité des gens à lire la documentation d'une langue ne rend pas les décisions de la langue erronées. Comme le note Mladen, Perl et Ruby utilisent également ces opérateurs supplémentaires, et avec les mêmes priorités. Il permet des constructions telles que $foo and bar(), qui sont de bons raccourcis pour les instructions if. Si un comportement inattendu (d'une mauvaise documentation, ou de ne pas le lire) était une raison de ne pas utiliser quelque chose, nous ne parlerions pas du tout de l'utilisation de PHP.
Altreus
2
J'ai passé 3 minutes pour trouver la mauvaise ligne: $ this = true , :( et qu'en est-il de $ trueiness = ($ this et $ that); c'est mieux pour moi :)
Dmitriy Kozmenko
6
Je suis d'accord avec Dmitriy - le fait de mettre l'évaluation booléenne entre parenthèses aide à clarifier l'intention du code. Je pense que l'opérateur et sa fonction tels qu'ils existent maintenant sont précieux et cohérents avec les autres langages, c'est le travail du programmeur de comprendre le langage.
Jon z
43

Selon la façon dont il est utilisé, il peut être nécessaire et même pratique. http://php.net/manual/en/language.operators.logical.php

// "||" has a greater precedence than "or"

// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;

// The constant false is assigned to $f and then true is ignored
// Acts like: (($f = false) or true)
$f = false or true;

Mais dans la plupart des cas, cela ressemble plus à un goût de développeur, comme chaque occurrence de cela que j'ai vue dans le cadre de CodeIgniter comme @Sarfraz l'a mentionné.

adamJLev
la source
2
Il convient de noter que le "vrai" n'est pas ignoré si cette expression fait partie d'une instruction plus large. Considérez le cas if ($f = false or true) $f = true;- le résultat serait que $fcela devient vrai à la fin, car l'expression s'évalue comme vraie dans l'ensemble.
Chris Browne
1
non, vous avez simplement écrasé la variable plus tard. l'expression est toujours évaluée à false, puis vous la remplacez par true dans la ligne suivante.
r3wt
2
En fait, il avait raison. Tout d'abord, la valeur $ffalse est affectée - mais la condition est évaluée à true, elle $fest donc remplacée. Si la condition est évaluée à faux, $felle ne sera jamais remplacée de toute façon.
ahouse101
Il est ridicule de suggérer aux développeurs de suivre leur propre goût. Oubliez le cauchemar d'un autre développeur en essayant de maintenir le même code, le développeur qui a écrit le code lui - même serait de faire des erreurs sémantiques dans un code écrit car il / elle préfère andplus &&, où andfonctionne comme prévu que dans certaines situations et &&fonctionne comme prévu dans tous les situations.
ADTC
13

Pour des raisons de sécurité, je garde toujours entre parenthèses mes comparaisons et je les espace. De cette façon, je n'ai pas à me fier à la priorité des opérateurs:

if( 
    ((i==0) && (b==2)) 
    || 
    ((c==3) && !(f==5)) 
  )
Capitaine Kenpachi
la source
29
Personnellement, je pense que l'ajout de parenthèses inutiles supplémentaires rend la lecture plus confuse que d'avoir juste ce dont vous avez besoin. Par exemple, je pense que c'est beaucoup plus facile à lire: if (($ i == 0 && $ b == 2) || ($ c == 3 && $ f! = 5))
rooby
4
Je pense que c'est le plus joli morceau de code que j'ai regardé toute la journée. Bon travail.
rm-vanda
Comme PHP est un langage interprété, il fonctionnera rapidement si vous n'utilisez pas d'espaces blancs inutiles ou de nouvelles lignes sur votre code. Si vous faites la même chose sur un langage compilé, la compilation prendra plus de temps mais ne prendra pas effet lors de l'exécution. Je ne veux pas dire que le faire une fois marquera une différence, mais sur une application entière utilisant php + javascript, les deux ont écrit comme l'exemple ... les temps de chargement seront certainement plus longs. Explication: les espaces blancs et les nouvelles lignes sont ignorés, mais pour les ignorer, ils doivent être vérifiés. Cela se produit au moment de l'exécution sur les langages interprétés et lors de la compilation sur ceux compilés.
JoelBonetR
@JoelBonetR si vous utilisez php opcache ou similaire, votre préoccupation concernant les temps de chargement est sans importance. J'espère que personne ne gère un site de production php sans lui ...
PeloNZ
@PeloNZ pour que vous puissiez écrire sale car il sera quand même mis en cache et le projet entier ne prendra qu'une seconde de plus à charger lors de l'actualisation, hein? Pour coder proprement, c'est pour vous et vos coéquipiers, les inquiétudes concernant les horaires n'étaient qu'un point que la plupart des gens ignorent ou ne savaient tout simplement pas.
JoelBonetR
11

La priorité diffère entre && et et (&& a une priorité plus élevée que and), ce qui cause de la confusion lorsqu'il est combiné avec un opérateur ternaire. Par exemple,

$predA && $predB ? "foo" : "bar"

renverra une chaîne alors que

$predA and $predB ? "foo" : "bar"

renverra un booléen .

arviman
la source
10

Depuis anda une priorité inférieure à celle que =vous pouvez utiliser dans l'affectation de condition:

if ($var = true && false) // Compare true with false and assign to $var
if ($var = true and false) // Assign true to $var and compare $var to false
Justinas
la source
2

Permettez-moi d'expliquer la différence entre «et» - «&&» - «&».

"&&" et "et" sont tous deux des opérations ET logiques et font la même chose, mais la priorité de l'opérateur est différente.

La priorité (priorité) d'un opérateur spécifie comment "étroitement" il lie deux expressions ensemble. Par exemple, dans l'expression 1 + 5 * 3, la réponse est 16 et non 18 car l'opérateur de multiplication ("*") a une priorité plus élevée que l'opérateur d'addition ("+").

Les mélanger ensemble en une seule opération pourrait vous donner des résultats inattendus dans certains cas, je recommande toujours d'utiliser &&, mais c'est votre choix.


D'un autre côté, "&" est une opération ET au niveau du bit . Il est utilisé pour l'évaluation et la manipulation de bits spécifiques dans la valeur entière.

Par exemple, si vous le faites (14 et 7), le résultat serait 6.

7   = 0111
14  = 1110
------------
    = 0110 == 6
Mahmoud Zalt
la source
1

Quelle version utilisez-vous?

Si les normes de codage pour la base de code particulière pour laquelle j'écris du code spécifient l'opérateur à utiliser, je vais certainement l' utiliser. Sinon, et le code dicte qui doit être utilisé (pas souvent, peut être facilement contourné) alors je vais l'utiliser. Sinon, probablement && .

Est «et» plus lisible que «&&»?

Est-il plus lisible pour vous ? La réponse est oui et non en fonction de nombreux facteurs dont le code autour de l'opérateur et même de la personne qui le lit!

|| il y a ~ différence?

Oui. Voir les opérateurs logiques pour ||et les opérateurs au niveau du bit pour ~.

salathe
la source
0

Je suppose que c'est une question de goût, bien que (à tort) les mélanger puisse provoquer des comportements indésirables:

true && false || false; // returns false

true and false || false; // returns true

Par conséquent, en utilisant && et || est plus sûr car ils ont la plus haute priorité. En ce qui concerne la lisibilité, je dirais que ces opérateurs sont assez universels.

MISE À JOUR : À propos des commentaires disant que les deux opérations retournent false ... eh bien, en fait, le code ci-dessus ne renvoie rien, je suis désolé pour l'ambiguïté. Pour clarifier: le comportement dans le second cas dépend de la façon dont le résultat de l'opération est utilisé. Observez comment la priorité des opérateurs entre en jeu ici:

var_dump(true and false || false); // bool(false)

$a = true and false || false; var_dump($a); // bool(true)

La raison en $a === trueest que l'opérateur d'affectation a priorité sur tout opérateur logique, comme cela est déjà très bien expliqué dans d'autres réponses.

nuqqsa
la source
16
Ce n'est pas vrai, ils retournent tous faux.
Jay
0

Voici un petit contre-exemple:

$a = true;
$b = true;
$c = $a & $b;
var_dump(true === $c);

production:

bool(false)

Je dirais que ce type de faute de frappe est beaucoup plus susceptible de causer des problèmes insidieux (de la même manière que =vs ==) et est beaucoup moins susceptible d'être remarqué que adn/ rotypos qui signalera comme des erreurs de syntaxe. Je trouve également et / ou est beaucoup plus facile à lire. FWIW, la plupart des frameworks PHP qui expriment une préférence (la plupart ne le font pas) spécifient et / ou. Je n'ai également jamais rencontré de cas réel et non artificiel où cela aurait eu de l'importance.

Synchro
la source
0

Un autre bel exemple utilisant des ifinstructions sans =opérations d'affectation.

if (true || true && false); // is the same as:
if (true || (true && false)); // TRUE

et

if (true || true AND false); // is the same as:
if ((true || true) && false); // FALSE

car ANDa une priorité inférieure et donc ||une priorité plus élevée.

Celles-ci sont différentes dans les cas de true, false, falseet true, true, false. Voir https://ideone.com/lsqovs pour un exemple détaillé.

Ken
la source