Ruby中if(value)和if(value.present?)的区别?(if语句中的隐式转换)

woobm2wo  于 11个月前  发布在  Ruby
关注(0)|答案(1)|浏览(151)

在运行一些输入代码后: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 valueif value.present?对待""{}[]是不同的,因为它们是确实存在的容器,但它们是空的。我的问题是-这是唯一的区别吗?当对if value进行隐式条件检查时,Ruby实际上在幕后使用了什么操作符?有没有一些文档或术语我可以查找到更多关于这种隐式转换的信息,以及一般情况?

ffscu2ro

ffscu2ro1#

显然,if valueif value.present?对待""{}[]的方式不同,因为它们是确实存在但为空的容器。我的问题是-这是唯一的区别吗?
在Ruby核心库和标准库中都没有名为present?的方法,因此不可能知道present?的功能。您必须查看该方法的文档才能确定它的功能。
如果您不知道该方法的来源,可以让Ruby帮助您,通过Object#method方法获取对该方法的引用,并使用the Method class中的一些方法,如Method#ownerMethod#source_location

present_method = value.method(:present?)

present_method.owner
present_method.source_location

字符串
根据名称,我们可以假设它是一个 predicate (通常,以?结尾的方法是 predicate ),用于检查某些内容的存在。
例如,下面是activesupport RubyGem中Object#present?的文档:

第一个月

如果对象不为空,则表示存在。
@return [真,假]
你在问:
在对if value进行隐式条件检查时,ruby实际上使用的是什么运算符?
无。没有隐含转换,也没有运算子。
“真实”的规则其实很简单:

  • false是 * 虚假的 *。
  • nil是假的。
  • 其他的都是正确的,包括00.0''[]{}

有没有一些文档或术语可以让我查找,以找到有关这种隐式转换和一般情况的更多信息?
这在几乎每一门关于Ruby的入门课程、书籍、视频或教程中都有涉及。有太多太多的名字。
如果你正在寻找一个“官方”的来源,它会变得有些棘手。
不幸的是,与许多其他编程语言不同,Ruby语言规范并不是作为一个单独的文档存在于一个单独的地方。Ruby没有一个单独的正式规范来定义某些语言结构的含义。
有几个资源,它们的 * 总和 * 可以被认为是Ruby编程语言的一种规范。
其中一些资源包括:

  • ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification--请注意,ISO Ruby规范是在2009-2010年左右编写的,其具体目标是使当时所有现有的Ruby实现都能轻松兼容。由于YARV和MacRuby只实现了Ruby 1.9+,MRI只实现了Ruby 1.8及更低版本,以及JRuby、XRuby、Ruby.NET和IronRuby(当时)只实现了Ruby 1.8的一个子集,这意味着ISO Ruby规范只包含Ruby 1.8和Ruby 1.9共有的特性。此外,ISORuby规范的目标是最小化并只包含编写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布尔值

一个对象被分为 * 类真对象 * 或 * 类假对象
只有
*falsenil是伪对象。false是类 * FalseClass * 的唯一示例(参见15.2.6),false-expression 计算的值nil*是类 * NilClass(见15.2.4)的唯一示例,nil-expression 对其求值(见11.5.4.8.2)。
除了
falsenil之外的对象都被分类为类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-clauseend**

  • then-clause*::

     * 分隔符**复合语句 *

    | separator?**then**compound-statement

  • else-clause*::

    **else * 复合语句 *

  • elsif-clause*::

    elsif * 表达式then-clause*

语义

  • if-expression* 的计算方法如下:

1.对 expression 求值。让V为结果值。
1.如果V是true对象,则计算 then-clausecompound-statementif-expression 的值是结果值。在这种情况下,elsif-clauses和 else-clause(如果有的话)不会被计算。
1.如果V是一个伪对象,并且没有 elsif-clauseelse-clause,那么 if-expression 的值是**nil
1.如果
V是一个假对象,并且如果没有 elsif-clause 但有 else-clause,则计算 else-clausecompound-statementif-expression 的值是结果值。
1.如果
V是一个伪对象,并且如果有一个或多个 elsif-clauses,则按如下方式计算 elsif-clauses的序列:
1.对每个 elsif-clauseexpression 按照它们在程序文本中出现的顺序进行求值,直到有一个 elsif-clauseexpression 求值为true对象。设
T为这个 elsif-clause
1.如果
T存在,则计算其 then-clausecompound-statementif-expression 的值是结果值。其他 elsif-clauses和 else-clause 跟在T后面,如果有的话,不计算。
1.如果
T不存在,并且存在 else-clause,则计算 else-clausecompound-statementif-expression 的值是结果值。
1.如果
T不存在,并且没有 else-clause,则 if-expression 的值为nil**。
这里有一个链接,指向language/if_spec.rb中ruby/spec的定义。

相关问题