【问题标题】:Is the ternary operator ?: defined as a method in Ruby?三元运算符 ?: 是否定义为 Ruby 中的方法?
【发布时间】:2019-02-01 00:37:07
【问题描述】:

我是 Ruby 新手,对三元运算符 ?: 的工作原理有点困惑。

据书Engineering Software as a Service: An Agile Approach Using Cloud Computing

每个操作都是对某个对象的方法调用并返回一个值。

从这个意义上说,如果三元运算符表示一个操作,它就是对带有两个参数的对象的方法调用。但是,我在Ruby's documentation 中找不到三元运算符代表的任何方法。三元运算符是否代表 Ruby 中的操作?上面提到的书的上述主张是错误的吗? Ruby 中的三元运算符真的只是 if ... then ... else ... end 语句的语法糖吗?

请注意: 我的问题与How do I use the conditional operator (? :) in Ruby? 有关,但与那个不同。我知道如何以该帖子中描述的方式使用三元运算符。我的问题是关于三元运算符在 Ruby 中的定义位置以及三元运算符是否定义为一个或多个方法。

【问题讨论】:

  • @ElliottFrisch 我的问题与那个有关,但与那个不同。我知道如何以该帖子中描述的方式使用ternary operator。我的问题是关于 ternary operator 在 Ruby 中的定义位置以及 ternary operator 是否定义为一个或多个方法。
  • 此表可能有用。并非 Ruby 中的所有运算符都是对象上的方法。 techotopia.com/index.php/…
  • @MarcBaumbach 根据该表,三元运算符没有作为方法实现。我想我读的书中的说法是错误的。你怎么看?您认为我对书中的主张的解释有误吗?
  • 我不认为您对它的解释有误,我认为这本书不正确或不够具体。一般来说,Ruby 确实将几乎所有东西都视为一个对象,而其他语言通常不这样做。 nil 就是一个很好的例子。

标签: ruby ternary-operator


【解决方案1】:

Ruby 中的三元运算符真的只是 if ... then ... else ... end 语句的语法糖吗?

是的。

来自doc/syntax/control_expressions.rdoc

您也可以使用?: 编写if-then-else 表达式。这个三元 if:

input_type = gets =~ /hello/i ? "greeting" : "other"

和这个if表达式一样:

input_type =
  if gets =~ /hello/i
    "greeting"
  else
    "other"
  end

"根据这本书,“每个操作都是对某个对象的方法调用并返回一个值。”从这个意义上说,如果三元运算符表示一个操作,它就是对一个对象的方法调用,它有两个论据。"

ifunlesswhileuntil 不是运算符,它们是控制结构。它们的修饰符版本出现在operator precedence table 中,因为它们需要具有优先级才能被解析。他们只是检查他们的条件是真还是假。在 Ruby 中这很简单,只有 falsenil 是错误的。其他都是真的。

运算符是 !+*[]。他们是unarybinary。您可以通过在各种对象上调用 .methods.sort 来查看它们的列表。比如……

2.4.3 :004 > 1.methods.sort
 => [:!, :!=, :!~, :%, :&, :*, :**, :+, :+@, :-, :-@, :/, :<, :<<, :<=, :<=>, :==, :===, :=~, :>, :>=, :>>, :[], :^, :__id__, :__send__, etc...

请注意,在Smalltalk 中,Ruby 大量借鉴了它,所有内容实际上都是一个方法调用。 Including the control structures.

【讨论】:

  • Smalltalk 的起源和链接非常有趣,非常感谢。
  • __send__ 是否是运营商值得商榷。我会说这只是一种方法。
  • @Stefan 看来你是对的。我以为所有方法调用都调用了__send__
  • @Schwern 谢谢你的回答。现在,我知道?: 不是由方法实现的。但是,我对您帖子的最后一部分感到有些困惑。 ?: 不是 Ruby 中的运算符,尽管它不是由方法实现的吗?对象上的.methods 返回一个列表,该列表仅包含作为方法实现的实体。
  • @Schwern 我同意你的观点,?: 非常适合 Ruby 中的控制结构。但是,在向您和本文中的其他人学习了很多之后,我仍然将?: 视为运营商,原因有两个。 1. ?: 控制执行流程这一事实不应取消其作为操作的资格。 (|| 在 Ruby 中也是如此;?:|| 在 C 中也是如此。) 2. ?: 在 Ruby 中相对于其他运算符具有优先级。我们的分歧实际上只是术语。感谢您的帮助。
【解决方案2】:

Ruby 中的三元运算符真的只是 if ... then ... else ... end 语句的语法糖吗?

(另一个)

这是a ? b : c 的解析树:

$ ruby --dump=parsetree -e 'a ? b : c'
###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_PRELUDE (line: 1)
#     +- nd_head:
#     |   (null node)
#     +- nd_body:
#     |   @ NODE_IF (line: 1)
#     |   +- nd_cond:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :a
#     |   +- nd_body:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :b
#     |   +- nd_else:
#     |       @ NODE_VCALL (line: 1)
#     |       +- nd_mid: :c
#     +- nd_compile_option:
#         +- coverage_enabled: false

这是if a then b else c end 的解析树:

$ ruby --dump=parsetree -e 'if a then b else c end'
###########################################################
## Do NOT use this node dump for any purpose other than  ##
## debug and research.  Compatibility is not guaranteed. ##
###########################################################

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_PRELUDE (line: 1)
#     +- nd_head:
#     |   (null node)
#     +- nd_body:
#     |   @ NODE_IF (line: 1)
#     |   +- nd_cond:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :a
#     |   +- nd_body:
#     |   |   @ NODE_VCALL (line: 1)
#     |   |   +- nd_mid: :b
#     |   +- nd_else:
#     |       @ NODE_VCALL (line: 1)
#     |       +- nd_mid: :c
#     +- nd_compile_option:
#         +- coverage_enabled: false

它们是相同的。

在许多语言中,?: 是一个表达式,而if-then-else 是一个语句。在 Ruby 中,两者都是表达式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-06
    • 2016-01-29
    • 2013-04-29
    • 2021-10-06
    • 1970-01-01
    • 2011-07-12
    • 2011-07-12
    • 2016-10-04
    相关资源
    最近更新 更多