Antworten:
Nicht nicht. Es wird verwendet, um einen Wert in einen Booleschen Wert umzuwandeln:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
Es ist jedoch normalerweise nicht erforderlich, es zu verwenden, da die einzigen falschen Werte für Ruby nil
und false
sind. Daher ist es normalerweise am besten, diese Konvention beizubehalten.
Betrachten Sie es als
!(!some_val)
Eine Sache, für die es zu Recht verwendet wird, ist die Verhinderung der Rückgabe eines großen Datenblocks. Beispielsweise möchten Sie wahrscheinlich nicht 3 MB Bilddaten in Ihrer has_image?
Methode zurückgeben, oder Sie möchten möglicherweise nicht Ihr gesamtes Benutzerobjekt in der logged_in?
Methode zurückgeben. Using !!
konvertiert diese Objekte in ein einfaches true
/ false
.
.nil?
anstatt zu benutzen !!
? Ist da ein Unterschied?
!!true #=> true
undtrue.nil? #=> false
!
bedeutet negieren booleschen Zustand, zwei !
s ist nichts Besonderes, außer einer doppelten Negation.
!true == false
# => true
Es wird häufig verwendet, um eine Methode zu zwingen, einen Booleschen Wert zurückzugeben. Es erkennt jede Art von Wahrhaftigkeit, wie z. B. Zeichenfolge, Ganzzahlen und was nicht, und verwandelt sie in einen Booleschen Wert.
!"wtf"
# => false
!!"wtf"
# => true
Ein realistischerer Anwendungsfall:
def title
"I return a string."
end
def title_exists?
!!title
end
Dies ist nützlich, wenn Sie sicherstellen möchten, dass ein Boolescher Wert zurückgegeben wird. IMHO ist es irgendwie sinnlos zu sehen, dass beide if 'some string'
und if true
genau der gleiche Fluss sind, aber einige Leute finden es nützlich, einen Booleschen Wert explizit zurückzugeben.
title
, können Sie auch das nächste tun ... Ich nehme an
Beachten Sie, dass diese Redewendung auch in anderen Programmiersprachen vorhanden ist. C hatte keinen intrinsischen bool
Typ, daher wurden alle Booleschen int
Werte stattdessen mit kanonischen Werten von 0
oder eingegeben 1
. Nimmt dieses Beispiel (zur Verdeutlichung Klammern hinzugefügt):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
Die "Nicht-Nicht" -Syntax konvertiert jede Ganzzahl ungleich Null in 1
den kanonischen booleschen wahren Wert.
Im Allgemeinen finde ich es jedoch viel besser, einen vernünftigen Vergleich anzustellen, als diese ungewöhnliche Redewendung zu verwenden:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
Es ist nützlich, wenn Sie ein exklusives oder tun müssen . Kopie von Matt Van Horns Antwort mit geringfügigen Änderungen:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
Ich habe es verwendet, um sicherzustellen, dass zwei Variablen entweder beide null oder beide nicht null sind.
raise "Inconsistency" if !!a ^ !!b
Es ist "doppelt negativ", aber die Praxis wird entmutigt. Wenn Sie Rubocop verwenden , werden Sie feststellen , dass es sich bei einem solchen Code mit einem beschwertStyle/DoubleNegation
Verstoß .
Die Begründung lautet:
Da dies sowohl kryptisch und in der Regel überflüssig ist, sollte es vermieden werden , [dann paraphrasieren:] Wechsel
!!something
zu!something.nil?
!!false # => false
während!false.nil? # => true
!(foo.nil? || foo == false)
- ausführlicher, ja, aber weniger kryptisch.
Zu verstehen, wie es funktioniert, kann hilfreich sein, wenn Sie beispielsweise eine Aufzählung in einen Booleschen Wert konvertieren müssen. Ich habe Code, der genau das mit dem classy_enum
Edelstein macht:
class LinkStatus < ClassyEnum::Base
def !
return true
end
end
class LinkStatus::No < LinkStatus
end
class LinkStatus::Claimed < LinkStatus
def !
return false
end
end
class LinkStatus::Confirmed < LinkStatus
def !
return false
end
end
class LinkStatus::Denied < LinkStatus
end
Dann habe ich im Service-Code zum Beispiel:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
Tatsächlich ist der Bangbang-Operator zu dem geworden, was ich sonst als Methode namens to_bool geschrieben hätte.