Bon, ce n’est pas vraiment un opérateur, mais l’idiome est assez répandu et peut surprendre. Il est utilisé pour convertir nil en false, ce qui peut éviter des tests spécifiques comme if variable.nil?
Deux petits rappels :
- ! est l’opérateur de négation logique.
- Seuls false et nil ont la valeur booléenne FAUX. Tout le reste est vrai (y compris 0, la chaîne de caractère vide, etc.
Nous en déduisons la table de vérité suivante :
| variable | !variable | !!variable |
| * | false | true |
| false | true | false |
| nil | true | false |
* = n’importe quoi sauf nil ou false, donc de valeur booléenne true.
CQFD.
3 Comments
Ce genre d’idiome ne sert à rien en pratique, où disons que tous les cas de figures où je l’ai vu utilisé, j’ai pu le retirer sans aucun problème.
De même que les tests if variable.nil?, même si on les voit partout dans le code de Rails, ils ne servent à rien, il suffit de d’inverser la logique avec unless variable par exemple.
D’ailleurs variable.nil? peut renvoyer une erreur, car si variable n’est pas définie, l’interpréteur va rouspéter avec undefined local variable or method ‘variable’.
Et heureusement que nil est un objet (un peu particulier qui descend de NilClass si on défini variable=nil par exemple), car théoriquement nil.nil?() devrait planter, car on ne devrait pas pouvoir invoquer une méthode sur un objet qui n’existe pas.
De fait je n’utilise jamais !!
Par contre le test .nil? est utile. D’une part, nil n’est pas équivalent à false. D’autre part, dans bien des cas, inverser la logique nuit à la lisibilité de l’expression.
nil?() c’est un appel supplémentaire qui peut être économisé. Oui je sais « premature optimization is the root of evil », mais là c’est gratuit et ça améliore la lisibilité.
Et puis c’est facile de passer de if à unless ou bien d’inverser un else. Enfin quand je vois des nil? de partout ça me pique les yeux.
nil n’est pas équivalent à false, mais si on teste pour nil?() c’est qu’on teste si la valeur est définie, et on sait que si la valeur n’est pas définie ça s’évalue à false, donc c’est équivalent.