在运行一些输入代码后:array = [nil, false, [], {}, {a: 1}, "", [0], [nil], NoMethodError]
def same_value?(value)
a = false
b = false
if value
a = true
end
if value.present?
b = true
end
[value, a == b]
end
个字符
我收到的响应=> [[nil, true], [false, true], [[], false], [{}, false], [{:a=>1}, true], ["", false], [[0], true], [[nil], true], [NoMethodError, true]]
。
所以,显然if value
和if value.present?
对待""
、{}
和[]
是不同的,因为它们是确实存在的容器,但它们是空的。我的问题是-这是唯一的区别吗?当对if value
进行隐式条件检查时,Ruby实际上在幕后使用了什么操作符?有没有一些文档或术语我可以查找到更多关于这种隐式转换的信息,以及一般情况?
1条答案
按热度按时间ffscu2ro1#
显然,
if value
和if value.present?
对待""
、{}
和[]
的方式不同,因为它们是确实存在但为空的容器。我的问题是-这是唯一的区别吗?在Ruby核心库和标准库中都没有名为
present?
的方法,因此不可能知道present?
的功能。您必须查看该方法的文档才能确定它的功能。如果您不知道该方法的来源,可以让Ruby帮助您,通过
Object#method
方法获取对该方法的引用,并使用theMethod
class中的一些方法,如Method#owner
或Method#source_location
:字符串
根据名称,我们可以假设它是一个 predicate (通常,以
?
结尾的方法是 predicate ),用于检查某些内容的存在。例如,下面是
activesupport
RubyGem中Object#present?
的文档:第一个月
如果对象不为空,则表示存在。
@return [真,假]
你在问:
在对
if value
进行隐式条件检查时,ruby实际上使用的是什么运算符?无。没有隐含转换,也没有运算子。
“真实”的规则其实很简单:
false
是 * 虚假的 *。nil
是假的。0
、0.0
、''
、[]
、{}
。有没有一些文档或术语可以让我查找,以找到有关这种隐式转换和一般情况的更多信息?
这在几乎每一门关于Ruby的入门课程、书籍、视频或教程中都有涉及。有太多太多的名字。
如果你正在寻找一个“官方”的来源,它会变得有些棘手。
不幸的是,与许多其他编程语言不同,Ruby语言规范并不是作为一个单独的文档存在于一个单独的地方。Ruby没有一个单独的正式规范来定义某些语言结构的含义。
有几个资源,它们的 * 总和 * 可以被认为是Ruby编程语言的一种规范。
其中一些资源包括:
String
进行了非常广泛的指定(因为它们在Ruby 1.8和Ruby 1.9之间有了很大的变化),显然它也没有指定在编写ISO Ruby规范之后添加的特性,例如Ractors或Pattern Matching。然而,自从大约30年前Ruby的第一个版本以来,truthiness 的定义就没有改变过,所以ISO Ruby语言规范的这一部分仍然是最新的。
The Ruby Spec Suite aka
ruby/spec
--注意,ruby/spec
很不幸还远远没有完成。但是,我很喜欢它,因为它是用Ruby编写的,而不是用“ISO标准语”编写的,这对于Ruby用户来说更容易阅读,而且它还可以作为一个可执行的一致性测试套件。The Ruby Programming Language by David Flanagan and Yukihiro 'matz' Matsumoto-这本书是由大卫Flanagan和Ruby的创建者matz共同编写的,作为Ruby的语言参考。
Programming Ruby by Dave Thomas, Andy Hunt, and Chad Fowler-这本书是第一本关于Ruby的英文书,长期以来一直是Ruby的标准介绍和描述。这本书还首次记录了Ruby核心库和标准库,作者们将这些文档捐赠给了社区。
Ruby Issue Tracking System,特别是Feature sub-tracker-但是,请注意,不幸的是,社区在区分关于Ruby编程语言的标签和关于YARV Ruby实现的标签方面非常非常糟糕:它们在跟踪器中混合在一起。
Ruby Developer Meetings的会议日志。(同样的问题:Ruby和YARV混合在一起。)
mailing lists的新特性经常被讨论,特别是ruby-core (English)和ruby-dev (Japanese)邮件列表(同样的问题再次出现)。
Ruby documentation--同样,请注意,本文档是从YARV的源代码生成的,并不区分Ruby的特性和YARV的特性。
在过去,曾经有过几次对Ruby规范进行形式化修改的尝试,比如Ruby Change Request (RCR)和Ruby Enhancement Proposal (REP)过程,但都没有成功。
如果这些都失败了,你需要检查流行的Ruby实现的源代码,看看它们实际上是做什么的。请注意复数:你必须看多个,理想情况下是所有的,只看一个实现 * 不可能告诉你 * 你所看到的是这个特定实现的一个实现怪癖,还是一个普遍认同的-Ruby语言的行为。
以下是ISO/IEC 30170:2012 * 信息技术-编程语言- Ruby* 规范中对 * 真实性 * 的定义:
6.6布尔值
一个对象被分为 * 类真对象 * 或 * 类假对象 。
只有*
false
和nil
是伪对象。false
是类 *FalseClass
* 的唯一示例(参见15.2.6),false-expression 计算的值nil
*是类 *NilClass
(见15.2.4)的唯一示例,nil-expression 对其求值(见11.5.4.8.2)。除了
false
和nil
之外的对象都被分类为类true对象。true
**是类 *TrueClass
(参见15.2.5)的唯一示例,一个 * true表达式 * 对其求值(参见11.5.4.8.3)。以下是ISO/IEC 30170:2012 * 信息技术-编程语言- Ruby 规范中 *
if
表达式 * 的定义:11.5.2.2.2
if
表达式安装
if-expression*::
if
* 表达式then-clauseelsif-clauseelse-clause?end
**then-clause*::
| separator?**
then
**compound-statementelse-clause*::
**
else
* 复合语句 *elsif-clause*::
elsif
* 表达式then-clause*语义
1.对 expression 求值。让V为结果值。
1.如果V是true对象,则计算 then-clause 的 compound-statement。if-expression 的值是结果值。在这种情况下,elsif-clauses和 else-clause(如果有的话)不会被计算。
1.如果V是一个伪对象,并且没有 elsif-clause 和 else-clause,那么 if-expression 的值是**
nil
。1.如果V是一个假对象,并且如果没有 elsif-clause 但有 else-clause,则计算 else-clause 的 compound-statement。if-expression 的值是结果值。
1.如果V是一个伪对象,并且如果有一个或多个 elsif-clauses,则按如下方式计算 elsif-clauses的序列:
1.对每个 elsif-clause 的 expression 按照它们在程序文本中出现的顺序进行求值,直到有一个 elsif-clause 的 expression 求值为true对象。设T为这个 elsif-clause。
1.如果T存在,则计算其 then-clause 的 compound-statement。if-expression 的值是结果值。其他 elsif-clauses和 else-clause 跟在T后面,如果有的话,不计算。
1.如果T不存在,并且存在 else-clause,则计算 else-clause 的 compound-statement。if-expression 的值是结果值。
1.如果T不存在,并且没有 else-clause,则 if-expression 的值为
nil
**。这里有一个链接,指向
language/if_spec.rb
中ruby/spec的定义。