web-dev-qa-db-fra.com

Un opérateur ternaire à triple emboîtement quelque peu douloureux

J'ai parcouru Raphael.js le code source pour découvrir comment il a converti les valeurs RVB en HSB. J'ai découvert la fonction dans laquelle il l'a fait et j'étais en train de le convertir en Python quand j'ai rencontré cet opérateur ternaire à triple emboîtement de Nice:

H = (C == 0 ? null :
    V == r ? (g - b) / C :
    V == g ? (b - r) / C + 2 :
             (r - g) / C + 4
    );

Cela m'a jeté pour une boucle parce que Python n'a pas le même type d'opérateur ternaire que Javascript. J'ai passé un peu de temps à le parcourir et j'ai finalement haché ce code quelque peu plus sain (en utilisant uniquement si/sinon) hors de lui:

if (C == 0) {
    H = null;
} else {
    if(V == r) {
        H = (g - b) / C;
    } else {
        if(V == g) {
            H = (b - r) / C + 2;
        } else {
            H = (r - g) / C + 4;
        }
    }
}

Mon interprétation était-elle correcte? Je ne pose cette question que parce que si ce n'est pas correct, je suis confronté à un lot de débogage. Donc. L'ai-je "compris"?

24

Je pense que vous pouvez avoir ceci pour éviter l'imbrication profonde:

var H

if(C == 0){
    H = null;
}
else if(V == r){
    H = (g - b) / C;
}
else if (V == g){
    H = (b - r) / C + 2;
}
else {
    H = (r - g) / C + 4;
}
26
Joseph

À mon goût personnel, un ternaire imbriqué soigneusement aligné bat le gâchis if-else:

const H =
  C == 0 ? null            :
  V == r ? (g - b) / C     :
  V == g ? (b - r) / C + 2 :
           (r - g) / C + 4 ;
H = C == 0 
    ? null 
    : V == r 
        ? (g - b) / C 
        : V == g 
            ? (b - r) / C + 2 
            : (r - g) / C + 4

J'ai vu Dan Abramov utiliser ce modèle de placement en retrait. Bien que je n'aime pas la façon dont l'opérateur conditionnel ? ne suit plus visuellement la condition, je préfère cela à quelque chose comme l'exemple de @ lolmaus en ce que l'indentation sera toujours cohérente quelle que soit la taille du conditionnel.

En fait, vous commencez à le voir comme ? vrai : false qui est visuellement intuitif ici. Et de cette façon, je trouve que le ternaire est beaucoup plus facile à repérer et à différencier du code environnant.

6
ssomnoremac

La même logique peut être écrite de manière plus simple:

var H

if (C == 0)
    H = null;
else if (V == r)
    H = (g - b) / C;
else if (V == g)
    H = (b - r) / C + 2;
else
    H = (r - g) / C + 4;

Il est possible d'omettre les accolades car il y a une seule déclaration dans chaque condition. Et étant donné que les conditions s'excluent mutuellement, en utilisant else if est beaucoup plus clair que l'imbrication ifs.

5
Óscar López

Si votre base de code JavaScript contient des instructions ternaires imbriquées comme celle en question, envisagez de convertir la mise en forme en instructions ternaires chaînées à la place.

H = (C == 0)           // Is C zero?
    ? null
    : (V == r)         // Is V equal to r?
    ? (g - b) / C
    : (V == g)         // Is V equal to g?
    ? (b - r) / C + 2
    : (r - g) / C + 4; // Fallback (default) value

Ils lisent simplement de haut en bas en ligne droite, renvoyant une valeur dès qu'ils atteignent un état véridique ou le repli.

- Les ternaires imbriqués sont excellents, Eric Elliot

Oui, c'est vrai (à part les différences de capitalisation). Pourtant, il peut être écrit plus propre sans parenthèses, lisible comme autre:

if (C == 0)
    h = null;
else if (V == r)
    h = (g - b) / C;
else if (V == g)
    h = (b - r) / C + 2;
else
    h = (r - g) / C + 4;
2
Bergi