当我发现这个值时,我正在对值进行序列化。Ruby有一个TrueClass
类和一个FalseClass
类,但是没有Boolean
类。我想知道为什么会这样。
我看到使用的一些优势Boolean
;例如,字符串解析可以集中在其上。
Ruby开发人员比我聪明,因此肯定有很多我看不见的充分理由。但是现在在我看来就像是用OneClass
和一个TwoClass
代替Fixnum
。
当我发现这个值时,我正在对值进行序列化。Ruby有一个TrueClass
类和一个FalseClass
类,但是没有Boolean
类。我想知道为什么会这样。
我看到使用的一些优势Boolean
;例如,字符串解析可以集中在其上。
Ruby开发人员比我聪明,因此肯定有很多我看不见的充分理由。但是现在在我看来就像是用OneClass
和一个TwoClass
代替Fixnum
。
bool
但是您必须包括stdbool.h
访问它(或使用_Bool
)。
Answers:
类的目的是将相似的对象或行为相似的对象组合在一起。1
并且2
非常相似,因此让他们处于同一个班级是很有意义的。true
而false
不过是不相似的。实际上,它们的全部目的在于它们彼此完全相反并且具有相反的行为。因此,它们不属于同一类。
您能否举例说明您将在Boolean
类中实现哪种常见行为?我什么都没想
让我们在行为只是外观,TrueClass
并FalseClass
具有:有完全4分的方法存在。不再。在每种情况下,这两种方法的作用恰恰相反。您如何以及为什么将其放在一个班级?
这是实现所有这些方法的方式:
class TrueClass
def &(other)
other
end
def |(_)
self
end
def ^(other)
!other
end
def to_s
'true'
end
end
现在反过来:
class FalseClass
def &(_)
self
end
def |(other)
other
end
def ^(other)
other
end
def to_s
'false'
end
end
当然,在Ruby中,幕后发生了很多“魔术”,这些魔术实际上TrueClass
并没有被处理,FalseClass
而是被硬连接到解释器中。这样的东西if
,&&
,||
和!
。然而,在Smalltalk,从中红宝石借了很多,包括概念FalseClass
和TrueClass
,所有这些都为实现方法,以及,你可以做同样的事情在Ruby中:
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
再次相反:
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
几年前,我只是为了好玩而写了上面的文章,甚至出版了。除了语法看起来不同,因为Ruby在我仅使用方法时使用特殊运算符,但它的行为与Ruby的内置运算符完全一样。实际上,我实际上接受了RubySpec一致性测试套件,并将其移植到我的语法中并通过了。
true.methods == false.methods
。在方法上,走路和听起来都像鸭子一样。
true
并false
没有分享任何实现。
eval
像这样更好!!eval("true")
吗?我个人更愿意为所有内容甚至使用bool()拥有.to_bool,但是很好。
Matz自己似乎在2004年的邮件列表中回答了这个问题。
他回答的简短版本:“现在可以正常工作,添加布尔值没有任何好处”。
我个人不同意。前述的“字符串解析”就是一个例子。另一个问题是,当您根据变量的类型对变量进行不同的处理时,具有“ Boolean”类的变量(即yml解析器)很方便-它将删除一个“ if”。它看起来也更正确,但这是个人观点。
可以通过一个拥有多个值的布尔类来管理true和false,但是该类对象必须具有内部值,因此每次使用都必须取消引用。
相反,Ruby将true和false视为长值(0和1),每个值对应于一种对象类类型(FalseClass和TrueClass)。通过使用两个类而不是单个布尔类,每个类不需要任何值,因此可以通过其类标识符(0或1)简单地进行区分。我相信这可以转化为Ruby引擎内部的显着速度优势,因为Ruby在内部可以将TrueClass和FalseClass视为需要从其ID值进行零转换的长值,而布尔对象必须在对其求值之前必须先取消引用。
由于在Ruby中,除了false
和以外的所有内容nil
默认情况下都为true,因此您只需向String添加解析。
这样的事情可能会起作用:
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
使用时,这将为您提供:
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
我认为Ruby背后的“大创意”的一部分是使程序具有您想要的固有行为(例如,布尔解析),而不是创建一个完全封装的类,使其生活在自己的命名空间中(例如,BooleanParser)。
"1"
在使用时等于true ==
;其他所有字符串均为假。PHP几乎是相反的,"0"
而且是""
==
错误的。所有其他字符串为true。Perl和Python(AFAIK)的工作方式类似于Ruby,所有字符串都是正确的。在Java中,每隔一个字符串Boolean.parseBoolean()
都会为true"true"
和false。C#Boolean.Parse()
将为您(在去除空格和缩进空白之后)为true,为"true"
false"false"
并抛出其他所有内容。
trueish?
),以明确表明使用此方法所做的假设是宽松且临时的,不基于任何标准。
在Ruby中,nil和false均为false,其他所有内容均为true。因此,不需要特定的布尔类。
你可以尝试一下 :
if 5
puts "5 is true"
end
5评估为真
if nil
puts "nil is true"
else
puts "nil is false"
end
将打印“ nil is false”
false
是错误的:)
主要原因仅仅是因为这样的事实,即与布尔类(暗示转换)相比,它现在比现在更容易实现布尔表达式。
正如孟格斯·庞(Mongus Pong)告诉您的那样,当您输入“ if”时,您要求解释器对事物进行评估,然后分支。如果您具有布尔类,则必须在分支之前将事物的评估转换为布尔值(再执行一步)。
请记住,这样的-> Boolean转换可以作为Boolean类中的Ruby方法使用。然后可以像其他任何Ruby方法一样动态地更改此方法,从而允许开发人员完全弄乱事情(实际上并不那么严重),但是显然,这不允许解释器按需优化测试。
您是否意识到它将用一个完整的方法调用来代替一些CPU指令操作,这在Ruby中非常昂贵(请记住“发送”方法处理)...
thing
在分支之前将的求值转换为布尔值”该语句背后的逻辑是什么?
正如其他人所说,您可以“修补” Ruby。创建自己的课程。这是我想到的。布尔类上的方法有些愚蠢,但在某些时候可以通过编程使用。
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
Boolean
?