【问题标题】:Is the assignment operator really "just" an operator?赋值运算符真的“只是”一个运算符吗?
【发布时间】:2020-08-13 08:19:58
【问题描述】:

我的问题是由this 关于 SO 的讨论引发的,但并未得出能够真正解释问题的答案。我在这里以稍微不同的方式“重写”它,因为我想更清楚真正的问题是什么,因此希望在这里得到答案。

考虑以下两个 Ruby 表达式:

  1. 1 * a - 3
  2. 1 && a = 3

从 Ruby 优先级表中,我们知道这里提到的运算符中,* 的优先级最高,其次是 -,然后是 &&,最后是 =

表达式没有括号,但是 - 正如我们可以在 irb 中验证的那样,在第一种情况下为 a 提供合适的值 - 它们被评估为好像括号被写为(1*a) - 3,分别为1 && (a=3)

第一个很容易理解,因为*的绑定比-强。

第二个不能这样解释。 && 的绑定比 = 强,所以如果只考虑优先级,解释应该是 (1 && a) = 3

关联性(= 是右关联的,- 是左关联的)也无法解释这种影响,因为关联性仅在我们有多个相同类型的运算符时才重要(例如 x-y-zx=y=z)。

赋值运算符中必须有一些特殊规则,我在我检查的文档中没有找到,特别是 assignmentsyntax 的文档。

有人可以指出,赋值运算符的这种特殊行为记录在哪里?还是我在这里错过/误解了什么?

【问题讨论】:

  • 你也可以开始赏金。
  • 我会考虑将其用于 this 问题,但必须等到它有资格获得赏金。我觉得原始问题的表述(不是我撰写的)并没有把问题带到重点。在我的重写中,我试图专注于最简单可重现的例子。
  • 在 SO 上阅读this question 的答案,似乎给出了答案。综上所述,赋值的左端有特定的允许值,所以本例中不应用优先规则。

标签: ruby syntax


【解决方案1】:

来自文档:https://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#assign

赋值表达式用于将对象赋值给变量等。赋值有时用作局部变量或类常量的声明。赋值表达式的左侧可以是:

变量 变量 `=' 表达式

右边有一个表达式,所以将表达式的结果赋值给变量

因此,您应该在遵循优先级之前查找表达式 (*)

1 && a = 3 基本上是两个“链式”表达式:

31 && 3

也许它更具可读性: 1 && a = 3 + 4 其中表达式为3 + 41 && 7,请参见:

1 && a = 3 + 4 #=> 7
1 && 7 #=> 7
res = 1 && a = 3 + 4
res #=> 7

(*) 优先表也有助于查找表达式(在链接文档中的运算符表达式段落中查找优先表):

表中= 上方的内容“形成”= 分配的表达式,下方的内容则不然。

例如:

1 + 3 and 2 + 4 #=> 4
a = 1 + 3 and b = 2 + 4 #=> 4
(a = 1 + 3) and (b = 2 + 4) #=> 4
a = (1 + 3 and b = 2 + 4) #=> 6

您还可以根据优先级表检查这些示例:

1 && 3 #=> 3
1 && a = 3 #=> 3
a #=> 3

3 and 1 #=> 3
3 and b = 1 #=> 3
b #=> 1

2 ** c = 2 + 1 #=> 8
c #=> 3

d = 2 ** 3
d #=> 8

e = 3
e **= 2
e #=> 9

【讨论】:

    【解决方案2】:

    我认为对1 && (a = 3) 的理解具有误导性,这是可以理解的。

    a = false
    b = 1
    b && a = 3
    b
    => 1
    a
    => 3
    

    afalse 时,为什么在&& 表达式中分配a?遇到false 值时,&& 表达式是否应该不返回?剧透,它确实return

    退一步,我们想到了&& 操作符控制逻辑流的目的。我们对声明的态度

    1 && a = 3
    

    假设如果anilfalse,则返回整个语句。好吧,不,解释器 是这样评估的:

    (1 && a) = 3
    

    如果anilfalse,解释器不会引发a,如果anilfalse,它也不返回左侧

    a = nil
    1 && a
    => nil # a was returned
    

    解释器返回变量,这就是为什么可以读取原始语句的原因:

    a = 3
    

    由于1 && a 返回a,这是一个可以由语句后半部分的= 操作数分配的变量。

    TLDR

    在您的原始示例中:1 既不是nil 也不是false,因此变量a(1 && a) 中返回,随后在a = 3 中分配

    【讨论】:

      【解决方案3】:

      可能是因为另一种解释不起作用:

      irb(main):003:0> (1 && a) = 3
      Traceback (most recent call last):
              3: from /home/w/.rbenv/versions/2.7/bin/irb:23:in `<main>'
              2: from /home/w/.rbenv/versions/2.7/bin/irb:23:in `load'
              1: from /home/w/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.3/exe/irb:11:in `<top (required)>'
      SyntaxError ((irb):3: syntax error, unexpected '=', expecting `end')
      (1 && a) = 3
               ^
      

      因此,也许 Ruby 以该语言可以合法解释的唯一方式将 1 &amp;&amp; a = 3 括起来。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-21
        • 2010-12-03
        • 2011-11-16
        • 2014-12-26
        • 2013-11-30
        • 2015-10-02
        • 2013-06-28
        • 1970-01-01
        相关资源
        最近更新 更多