`(a || = [])<< 1`与`(i || = 0)+ = 1`

时间:2012-10-14 04:02:39

标签: ruby syntax

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

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

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

此特定语法仅在与Arrays结合使用时才有效,因为我尝试使用其他类型返回语法错误。

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与其他类型区分开来是什么?

3 个答案:

答案 0 :(得分:5)

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

a += b

的语法糖
a = a + b

所以,

(i ||= 0) += 1

的语法糖
(i ||= 0) = (i ||= 0) + 1

这完全是非法的。

这与数组完全无关,你可以在这里看到:

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

(a ||= []) += [1]    # doesn't work

答案 1 :(得分:0)

左侧必须是变量。怎么样:

i = (i || 0) + 1

i = i ? i + 1 : 1

答案 2 :(得分:0)

您可以将这些受保护的语句用于提供将改变变量状态的操作的任何内容,例如:用于String的concat,&lt;&lt; for Array等。

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örgWMittag的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