2010-10-22 2 views
74

Duplicate possible:
What does !! mean in ruby?Rubis, !! opérateur (a/k/a la double-bang)

Salut,

Je suis nouveau à Ruby et ne trouve nulle part description de quoi "!!" veux dire.

Voici un exemple:

def signed_in? 
    !!current_user 
end 

Si cela est un double négatif, pourquoi ne pas dire:

def signed_in? 
    current_user 
end 

S'il vous plaît aider.

+0

Avez-vous regardé des questions qui vous ont été données après que vous ayez tapé le titre de votre question? – Nakilon

+4

Oui, il n'y avait rien là. J'ai effectivement trouvé une question similaire m'expliquant la deuxième question, mais j'ai dû chercher par "double bang" qui n'est pas si évident que vous pourriez le penser. – Vitaly

+3

Oui, l'algorithme des questions similaires est facilement manipulé lorsque des parties importantes du titre sont des caractères de ponctuation. – pkaeding

Répondre

98

Dans la plupart des langages de programmation, y compris Ruby, ! renverra l'opposé de la valeur booléenne de l'opérande. Ainsi, lorsque vous enchaînez deux points d'exclamation, il convertit la valeur en valeur booléenne.

121

Dans Ruby (et dans de nombreuses autres langues), de nombreuses valeurs sont évaluées à true dans un contexte booléen, et une poignée est évaluée à false. Dans Ruby, the only two things that evaluate to false are false (itself) and nil.

Si vous annulez quelque chose, cela force un contexte booléen. Bien sûr, cela le nie aussi. Si vous le doublez, il force le contexte booléen, mais renvoie la valeur booléenne appropriée.

Par exemple:

"hello" #-> this is a string; it is not in a boolean context 
!"hello" #-> this is a string that is forced into a boolean 
      # context (true), and then negated (false) 
!!"hello" #-> this is a string that is forced into a boolean 
      # context (true), and then negated (false), and then 
      # negated again (true) 
!!nil  #-> this is a false-y value that is forced into a boolean 
      # context (false), and then negated (true), and then 
      # negated again (false) 

Dans votre exemple, la méthode signed_in? doit renvoyer une valeur booléenne (comme indiqué par convention par le caractère ?). La logique interne utilisée pour déterminer cette valeur est en vérifiant si la variable current_user est définie. Si elle est définie, elle évaluera true dans un contexte booléen. Sinon, il sera évalué comme faux. La double négation force la valeur de retour à être un booléen.

+0

donc! "" Force à ** vrai ** et !! "" à ** faux ** ou la chaîne vide est-elle également vraie? – berto77

+1

'!" "' Est 'false', car les seules valeurs false-y sont' false' et 'nil'. Tout le reste est vérité-y: http://phrogz.net/ProgrammingRuby/language.html#truthvalues ​​J'ai édité ma réponse pour rendre ceci plus clair. – pkaeding

+2

C'est la meilleure réponse parce qu'elle explique pourquoi. On dirait que le même type de piratage que l'on voit parfois en Java convertit un int en String en ajoutant un "" à celui-ci (que je ne préconise pas pour - je crois que c'est une mauvaise pratique en Java). Étant donné que c'est une mauvaise pratique en Java, je ne comprends pas pourquoi des langues comme Ruby l'adoptent. Tout pour utiliser le moins de caractères possible? –

27

!! est juste ! (l'opérateur de négation booléenne) écrit deux fois. Il va nier l'argument, puis nier la négation. C'est utile car vous pouvez l'utiliser pour obtenir un booléen de n'importe quelle valeur. Le premier ! convertira l'argument en un booléen, par ex. true si c'est nil ou false, et false sinon. La seconde annulera à nouveau cela afin que vous obteniez la valeur booléenne de l'argument, false pour nil ou false, true pour à peu près tout le reste.

Dans Ruby, vous pouvez utiliser n'importe quelle valeur dans une instruction if, par ex. if current_user s'exécutera si l'utilisateur actuel n'est pas nil. La plupart du temps c'est génial car cela nous évite de taper des tests explicites (comme if !current_user.nil?, qui est au moins six caractères de plus). Mais parfois, cela peut être très déroutant si vous renvoyez un objet lorsque la méthode implique qu'il renvoie un booléen. Les méthodes dont le nom se termine par ? doivent renvoyer des valeurs truey ou falsy, c'est-à-dire qu'elles renvoient quelque chose qui sera évalué à true ou false. Cependant, il peut être vraiment désordonné si signed_in? a renvoyé un objet utilisateur.Par exemple si vous essayez de déboguer pourquoi un code qui utilise signed_in? ne fonctionne pas, vous serez probablement très confus quand un objet utilisateur apparaît où vous attendiez true ou false. Dans cette situation, il est utile d'ajouter !! avant le return car cela garantissait que la valeur truey ou falsy sera retournée comme true ou false.

3

Comme vous l'avez bien compris, il s'agit d'une utilisation double-négative de l'opérateur !. Cela dit, même si cela peut être un raccourci pour vérifier si une variable peut être nulle ou non, OMI trop concis. Jetez un oeil à this et this après. Notez que dans Ruby, tester quelque chose à zéro donnera une évaluation fausse.