Ich habe daran gearbeitet, Werte zu serialisieren, als ich davon erfuhr. Ruby hat eine TrueClass
Klasse und eine FalseClass
Klasse, aber es gibt keine Boolean
Klasse. Ich würde gerne wissen, warum das so ist.
Ich sehe einige Vorteile in der Verwendung von a Boolean
; Beispielsweise könnte das Parsen von Zeichenfolgen darauf zentralisiert werden.
Ruby-Entwickler sind schlauer als ich, daher muss es viele gute Gründe geben, die ich einfach nicht sehe. Aber im Moment sieht es für mich so aus, als hätte ich OneClass
ein TwoClass
statt Fixnum
.
ruby
language-design
Kikito
quelle
quelle
Boolean
?bool
aber Sie müssen ihn einschließen,stdbool.h
um darauf zuzugreifen (oder ihn zu verwenden_Bool
).Antworten:
Der Zweck einer Klasse besteht darin, ähnliche Objekte oder Objekte mit ähnlichem Verhalten zu gruppieren.
1
und2
sind sehr ähnlich, daher ist es vollkommen sinnvoll, dass sie in derselben Klasse sind.true
und sindfalse
jedoch nicht ähnlich. In der Tat ist ihr springender Punkt, dass sie genau das Gegenteil voneinander sind und ein entgegengesetztes Verhalten haben. Daher gehören sie nicht zur selben Klasse.Können Sie ein Beispiel dafür geben, welche Art von allgemeinem Verhalten Sie in einer
Boolean
Klasse implementieren würden ? Mir fällt nichts ein.Schauen wir uns das Verhalten an
TrueClass
undFalseClass
haben: Es gibt genau vier Methoden. Nicht mehr. Und in jedem Einzelfall machen die beiden Methoden genau das Gegenteil . Wie und warum würden Sie das in eine einzelne Klasse einordnen?So implementieren Sie all diese Methoden:
class TrueClass def &(other) other end def |(_) self end def ^(other) !other end def to_s 'true' end end
Und jetzt umgekehrt:
class FalseClass def &(_) self end def |(other) other end def ^(other) other end def to_s 'false' end end
Zugegeben, in Ruby gibt es eine Menge "Magie", die sich hinter den Kulissen abspielt und die nicht wirklich von dem Dolmetscher gehandhabt
TrueClass
undFalseClass
vielmehr fest verdrahtet wird. Sachen wieif
,&&
,||
und!
. In Smalltalk, von dem Ruby viel geliehen hat, einschließlich des Konzepts vonFalseClass
undTrueClass
, werden all diese Methoden ebenfalls als Methoden implementiert, und Sie können dasselbe in Ruby tun:class TrueClass def if yield end def ifelse(then_branch=->{}, _=nil) then_branch.() end def unless end def unlesselse(_=nil, else_branch=->{}) ifelse(else_branch, _) end def and yield end def or self end def not false end end
Und wieder umgekehrt:
class FalseClass def if end def ifelse(_=nil, else_branch=->{}) else_branch.() end def unless yield end def unlesselse(unless_branch=->{}, _=nil) ifelse(_, unless_branch) end def and self end def or yield end def not true end end
Vor ein paar Jahren habe ich das oben genannte nur zum Spaß geschrieben und sogar veröffentlicht . Abgesehen von der Tatsache, dass die Syntax anders aussieht, weil Ruby spezielle Operatoren verwendet, während ich nur Methoden verwende, verhält es sich genau wie die eingebauten Operatoren von Ruby. Tatsächlich habe ich die RubySpec-Konformitätstestsuite übernommen und auf meine Syntax portiert, und sie besteht.
quelle
true.methods == false.methods
. Beide gehen und klingen methodisch wie Enten.true
undfalse
nicht jede Implementierung teilen.eval
als so etwas zu tun!!eval("true")
? Ich persönlich würde es vorziehen, .to_bool für alles oder sogar bool () zu haben, aber es ist in Ordnung.Es scheint, dass Matz selbst diese Frage 2004 in einer Mailinglisten-Nachricht beantwortet hat .
Kurzfassung seiner Antwort: "Im Moment funktioniert es in Ordnung, das Hinzufügen eines Booleschen Werts bringt keinen Vorteil."
Persönlich stimme ich dem nicht zu; Das oben erwähnte "String-Parsing" ist ein Beispiel. Eine andere ist, dass, wenn Sie eine Variable je nach Typ unterschiedlich behandeln (dh einen yml-Parser), eine "Boolesche" Klasse hat, dies praktisch ist - sie entfernt ein "wenn". Es sieht auch korrekter aus, aber das ist eine persönliche Meinung.
quelle
Zitat von Matz im Ruby Forum (2013) :
quelle
true und false könnten von einer Booleschen Klasse verwaltet werden, die mehrere Werte enthält. Dann müsste das Klassenobjekt jedoch interne Werte haben und daher bei jeder Verwendung von der Referenz befreit werden.
Stattdessen behandelt Ruby true und false als lange Werte (0 und 1), von denen jeder einem Typ einer Objektklasse (FalseClass und TrueClass) entspricht. Durch die Verwendung von zwei Klassen anstelle einer einzelnen Booleschen Klasse benötigt jede Klasse keine Werte und kann daher einfach durch ihre Klassenkennung (0 oder 1) unterschieden werden. Ich glaube, dies führt zu erheblichen Geschwindigkeitsvorteilen innerhalb der Ruby-Engine, da Ruby intern TrueClass und FalseClass als lange Werte behandeln kann, für die keine Übersetzung von ihrem ID-Wert erforderlich ist, während ein Boolesches Objekt de-referenziert werden müsste, bevor es ausgewertet werden kann .
quelle
Da in Ruby standardmäßig alles außer
false
undnil
als wahr ausgewertet wird, müssen Sie nur das Parsen zu String hinzufügen.So etwas könnte funktionieren:
class Object ## Makes sure any other object that evaluates to false will work as intended, ## and returns just an actual boolean (like it would in any context that expect a boolean value). def trueish?; !!self; end end class String ## Parses certain strings as true; everything else as false. def trueish? # check if it's a literal "true" string return true if self.strip.downcase == 'true' # check if the string contains a numerical zero [:Integer, :Float, :Rational, :Complex].each do |t| begin converted_number = Kernel.send(t, self) return false if converted_number == 0 rescue ArgumentError # raises if the string could not be converted, in which case we'll continue on end end return false end end
Bei Verwendung würde dies Ihnen Folgendes geben:
puts false.trueish? # => false puts true.trueish? # => true puts 'false'.trueish? # => false puts 'true'.trueish? # => true puts '0'.trueish? # => false puts '1'.trueish? # => true puts '0.0'.trueish? # => false puts '1.0'.trueish? # => true
Ich glaube, ein Teil der „großen Idee“ hinter Ruby besteht darin, das gewünschte Verhalten Ihrem Programm eigen zu machen (z. B. Boolesches Parsen) und stattdessen eine vollständig gekapselte Klasse zu erstellen, die in ihrer eigenen Namespace-Welt lebt (z. B. BooleanParser).
quelle
"1"
bei Verwendung nur true==
. Alle anderen Zeichenfolgen sind falsch. PHP ist fast das Gegenteil -"0"
und""
==
falsch; Alle anderen Zeichenfolgen sind wahr. Perl & Python (AFAIK) funktionieren wie Ruby - alle Zeichenfolgen sind wahr. In Java erhaltenBoolean.parseBoolean()
Sie"true"
für jede andere Zeichenfolge true und false. C #Boolean.Parse()
gibt Ihnen (nach dem Leerzeichen-Strippen und Downcasing) wahr"true"
, falsch für"false"
und wirft auf alles andere.trueish?
) zu geben, der deutlich macht, dass die mit dieser Methode getroffenen Annahmen locker und ad hoc sind und nicht auf einem Standard basieren.In Ruby sind null und falsch falsch und alles andere ist wahr. Daher ist keine bestimmte boolesche Klasse erforderlich.
Du kannst es versuchen :
if 5 puts "5 is true" end
5 ergibt wahr
if nil puts "nil is true" else puts "nil is false" end
Gibt "nil is false" aus
quelle
false
das auch falsch ist :)Der Hauptgrund ist einfach die Tatsache, dass die Implementierung von Booleschen Ausdrücken viel schneller und einfacher ist als derzeit als bei einer Booleschen Klasse, die eine Konvertierung implizieren würde.
Wie Mongus Pong Ihnen sagte, wenn Sie "wenn" schreiben, bitten Sie den Dolmetscher, die Sache zu bewerten und dann zu verzweigen. Wenn Sie eine Boolesche Klasse hätten, müssten Sie die Auswertung der Sache vor dem Verzweigen in einen Booleschen Wert konvertieren (ein weiterer Schritt).
Denken Sie daran, dass eine solche -> Boolesche Konvertierung als Ruby-Methode in der Booleschen Klasse verfügbar ist. Diese Methode könnte dann dynamisch wie jede andere Ruby-Methode geändert werden, sodass Entwickler die Dinge völlig durcheinander bringen können (was in der Tat nicht so ernst ist), aber dies würde es dem Interpret eindeutig nicht ermöglichen, die Tests so zu optimieren, wie sie sollten.
Ist Ihnen klar, dass es einige CPU-Anweisungen durch einen vollständigen Methodenaufruf ersetzen würde, was in Ruby kostspielig ist (denken Sie an die Verarbeitung der "send" -Methode) ...
quelle
thing
in eine Boolesche Klasse konvertieren, bevor Sie verzweigen." Welche Logik steckt hinter dieser Anweisung?Wie andere gesagt haben, könnten Sie Ruby "patchen". Erstelle deine eigene Klasse. Hier ist etwas, das ich mir ausgedacht habe. Die Methoden in der Booleschen Klasse sind etwas albern, könnten aber irgendwann programmgesteuert nützlich sein.
class Boolean def self.new(bool) bool end def self.true true end def self.false false end end class FalseClass def is_a?(other) other == Boolean || super end def self.===(other) other == Boolean || super end end class TrueClass def is_a?(other) other == Boolean || super end def self.===(other) other == Boolean || super end end
quelle