红宝石中尴尬的三元评估

时间:2014-02-17 02:44:16

标签: ruby-on-rails ruby

我对红宝石中的一些三元表达感到非常困惑。

我有这个表达:

puts respond_to? "greeting".to_sym ? "hello" : "bye"

当然,这不是我在我的应用程序中所做的,只是为了让你看到。

事情是上面的表达式返回

false

如果方法存在则返回hello,如果方法不正确则返回bye

如果我将表达式更改为

puts respond_to?("greeting".to_sym) ? "hello" : "bye"

它会返回正确的内容,如果它存在则为“hello”,否则为“bye”。

为什么会这样?有什么东西关于ruby中的三元表达我不知道吗?

只是为了让您知道我的应用中的正确代码是:

respond_to?(path.to_sym) ? self.send(path) : "#"

返回数据库存储标题菜单的正确路径,如果不存在,则只需输入“#”以避免错误。

3 个答案:

答案 0 :(得分:5)

没有括号,似乎你的代码被解释为:

puts respond_to?("greeting".to_sym ? "hello" : "bye")

括号中的内容然后评估为“你好”,self显然没有回应,因此respond_to?返回false

这就是为什么每当对代码的操作顺序有任何疑问时使用括号总是一个好主意;它使您的代码更具可读性并消除了诸如此类的错误。

答案 1 :(得分:3)

如果没有respond_to的括号,则评估会像这样进行

"greeting".to_sym ? "hello" : "bye" #results in "hello"

puts respond_to? "hello" #results in false

将首先评估三元表达式,而不使用respond_to

的括号

答案 2 :(得分:2)

我在你的例子上运行ruby --dump parsetree(总是一个很好的方式来查看真正发生的事情)。在没有参数括号的版本中,三元组得到评估,respond_to?检查"hello"或“再见”。在第二种情况下,代码执行您的意图。

没有括号:

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_FCALL (line: 1)
#     +- nd_mid: :puts
#     +- nd_args:
#         @ NODE_ARRAY (line: 1)
#         +- nd_alen: 1
#         +- nd_head:
#         |   @ NODE_FCALL (line: 1)
#         |   +- nd_mid: :respond_to?
#         |   +- nd_args:
#         |       @ NODE_ARRAY (line: 1)
#         |       +- nd_alen: 1
#         |       +- nd_head:
#         |       |   @ NODE_IF (line: 1)
#         |       |   +- nd_cond:
#         |       |   |   @ NODE_CALL (line: 1)
#         |       |   |   +- nd_mid: :to_sym
#         |       |   |   +- nd_recv:
#         |       |   |   |   @ NODE_STR (line: 1)
#         |       |   |   |   +- nd_lit: "greeting"
#         |       |   |   +- nd_args:
#         |       |   |       (null node)
#         |       |   +- nd_body:
#         |       |   |   @ NODE_STR (line: 1)
#         |       |   |   +- nd_lit: "hello"
#         |       |   +- nd_else:
#         |       |       @ NODE_STR (line: 1)
#         |       |       +- nd_lit: "bye"
#         |       +- nd_next:
#         |           (null node)
#         +- nd_next:
#             (null node)

使用:

# @ NODE_SCOPE (line: 1)
# +- nd_tbl: (empty)
# +- nd_args:
# |   (null node)
# +- nd_body:
#     @ NODE_FCALL (line: 1)
#     +- nd_mid: :puts
#     +- nd_args:
#         @ NODE_ARRAY (line: 1)
#         +- nd_alen: 1
#         +- nd_head:
#         |   @ NODE_IF (line: 1)
#         |   +- nd_cond:
#         |   |   @ NODE_FCALL (line: 1)
#         |   |   +- nd_mid: :respond_to?
#         |   |   +- nd_args:
#         |   |       @ NODE_ARRAY (line: 1)
#         |   |       +- nd_alen: 1
#         |   |       +- nd_head:
#         |   |       |   @ NODE_CALL (line: 1)
#         |   |       |   +- nd_mid: :to_sym
#         |   |       |   +- nd_recv:
#         |   |       |   |   @ NODE_STR (line: 1)
#         |   |       |   |   +- nd_lit: "greeting"
#         |   |       |   +- nd_args:
#         |   |       |       (null node)
#         |   |       +- nd_next:
#         |   |           (null node)
#         |   +- nd_body:
#         |   |   @ NODE_STR (line: 1)
#         |   |   +- nd_lit: "hello"
#         |   +- nd_else:
#         |       @ NODE_STR (line: 1)
#         |       +- nd_lit: "bye"
#         +- nd_next:
#             (null node)