为什么我可以在Ruby中分配对应于数组的两个变量?

时间:2016-10-24 09:15:53

标签: ruby

经过大约一年的Ruby,我只是在某个地方看到了这个,我的思绪被吹了。为什么这个世界会起作用?

>> words = ['uno', 'dos']
=> ["uno", "dos"]
>> first, second = words
=> ["uno", "dos"]
>> first
=> "uno"
>> second
=> "dos"

具体来说,这是如何工作的:

>> first, second = ['uno', 'dos']

为什么我能这样做?它没有语法意义!

3 个答案:

答案 0 :(得分:8)

  

它没有语法意义

但这是Ruby语法的部分!在Ruby文档中,它被称为array decomposition

  

与方法参数中的数组分解一样,您可以分解一个   使用括号分配期间的数组:

(a, b) = [1, 2]

p a: a, b: b # prints {:a=>1, :b=>2}
     

您可以将数组分解为更大的多重赋值的一部分:

a, (b, c) = 1, [2, 3]

p a: a, b: b, c: c # prints {:a=>1, :b=>2, :c=>3}
     

因为每次分解都被认为是你自己的多重赋值   可以使用*来收集分解中的参数:

a, (b, *c), *d = 1, [2, 3, 4], 5, 6

p a: a, b: b, c: c, d: d
# prints {:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]}

修改

正如Stefan在评论中指出的那样,如果右侧只有一个值,那么文档并没有提到数组分解也会隐式发生(即没有括号):

a, b = [1, 2]的作用类似于(a, b) = [1, 2]

答案 1 :(得分:3)

  

为什么我能这样做?它没有语法意义!

这是一个完美的感觉。这是并行分配的一个例子。

当您使用=时,=左侧的每个变量列表都会分配给=右侧的每个表达式列表。< / p>

first, second = ['uno', 'dos']
# is equivalent to
first, second = 'uno', 'dos'

如果左侧的变量多于右侧的表达式,则左侧变量将分配nil

first, second = 'uno'
first  #=> 'uno'
second #=> nil

至于

words = ['uno', 'dos']
first, second = words
first  #=> 'uno'
second #=> 'dos'

它没有将整个words数组分配给firstsecond留下nil,因为并行分配Ruby会尝试分解右侧表达式,并且这样做如果它是Array的实例。

[TIL] 此外,它尝试在右侧表达式上调用to_ary,如果它响应方法,则相应地分解为该对象的to_ary实现(积分到@Stefan):

string = 'hello world'
def string.to_ary; split end
first, second = string
first  #=> 'hello'
second #=> 'world'

答案 2 :(得分:0)

这称为多重赋值,方便一次分配多个变量。 示例

one, two = 1,2
puts one #=>1
puts two #=>2
one, two = [1,2] # this makes sense
one, two = 1  # obviously this doesn't it will assign nil to two

希望现在有点清楚