4

虽然我已经编写 Ruby 有一段时间了,但我一直在寻找改进我的风格的方法。

我已经习惯了一种特别简短、简洁的实例化 + 附加到数组的方法:

ruby-1.9.3-p194 :001 > (a ||= []) << 1
 => [1] 

这种特殊的语法似乎只在与数组一起使用时才有效,因为我尝试对其他类型执行此操作会返回语法错误。

ruby-1.9.3-p194 :002 > (i ||= 0) += 1
SyntaxError: (irb):2: syntax error, unexpected tOP_ASGN, expecting $end

(i ||= 0) += 1
            ^
from /usr/local/rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'

而且,还有字符串,虽然我非常希望这在之前的实验中不起作用。

ruby-1.9.3-p194 :003 > (s ||= '') += 'TEST'
SyntaxError: (irb):3: syntax error, unexpected tOP_ASGN, expecting $end

(s ||= '') += 'TEST'
             ^
from /usr/local/rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'

使用这种语法形式时,Array 与其他类型的区别是什么?

4

3 回答 3

5

在 Ruby 中,就像在大多数其他语言中一样,缩写赋值只是扩展形式的语法糖,即

a += b

是语法糖

a = a + b

所以,

(i ||= 0) += 1

是语法糖

(i ||= 0) = (i ||= 0) + 1

这简直是​​非法的。

这与数组完全无关,您可以在此处看到:

(s ||= '') << 'TEST' # works

(a ||= []) += [1]    # doesn't work
于 2012-10-14T04:11:13.573 回答
0

左边必须是一个变量。怎么样:

i = (i || 0) + 1

或者

i = i ? i + 1 : 1
于 2012-10-14T05:15:08.523 回答
0

您可以将这些受保护的语句用于提供将更改变量状态的操作的任何内容,例如用于字符串的 concat、用于数组的 << 等。

1.9.2p290 :111 > s = nil
 => nil 
1.9.2p290 :112 > (s ||= '').concat 'test'
 => "test" 
1.9.2p290 :113 > (s ||= '').concat 'test'
 => "testtest" 

对于某些类型,例如 FixNum,您实际上没有选项,因为您无法在没有分配的情况下更改状态,因此我们可以拥有的最接近的东西是 succ,但正如您所看到的,它不会更新存储的值

1.9.2p290 :130 > i = nil
 => nil 
1.9.2p290 :131 > (i || 0).succ
 => 1 
1.9.2p290 :132 > (i || 0).succ
 => 1 

对于此类类型,我推荐 Jörg W Mittag 的建议,i = (i || 0) + 1因为它非常干净并且很好地描绘了它的目的

1.9.2p290 :134 > i = nil
 => nil 
1.9.2p290 :135 > i = (i || 0) + 1
 => 1 
1.9.2p290 :136 > i = (i || 0) + 1
 => 2 
于 2012-10-14T07:45:51.277 回答