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

为什么我可以在Ruby中为数组分配两个对应的变量?,ruby,Ruby,大约一年的红宝石之旅后,我在某处看到了这一点,我的心都碎了。这到底是为什么 >> words = ['uno', 'dos'] => ["uno", "dos"] >> first, second = words => ["uno", "dos"] >> first => "uno" >> second => "dos" 具体来说,这是如何工作的: >> first, second = ['uno', 'dos

大约一年的红宝石之旅后,我在某处看到了这一点,我的心都碎了。这到底是为什么

>> words = ['uno', 'dos']
=> ["uno", "dos"]
>> first, second = words
=> ["uno", "dos"]
>> first
=> "uno"
>> second
=> "dos"
具体来说,这是如何工作的:

>> first, second = ['uno', 'dos']
为什么我可以这样做?这在句法上毫无意义

为什么我可以这样做?这在句法上毫无意义

这很有道理。这是并行分配的一个例子

使用
=
时,发生的情况是
=
左侧的每个变量列表都被分配给
=
右侧的每个表达式列表

first, second = ['uno', 'dos']
# is equivalent to
first, second = 'uno', 'dos'
如果左侧的变量多于右侧的表达式,则这些左侧变量将被分配为
nil

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

它并不是将整个
单词
数组分配给
第一个
而将
第二个
留给
nil
,因为在并行分配时,Ruby会尝试分解右侧表达式,如果它是数组的一个实例,它会这样做

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


这称为多重赋值,便于一次赋值多个变量。 范例

希望现在有点清楚

这在句法上毫无意义

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

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

(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]

您能详细说明一下吗?第一个是
,第二个是单词
?根据您的解释(左边的变量比右边的表达式多),这应该将
单词分配给
first
nil
分配给
second
@Stefan是的,在这方面,我的回答是误导和错误的。。我会考虑改写或删除,谢谢注意!它提出了一个问题,为什么一些对象在并行分配期间(或之前)分解,而另一些对象没有分解。此外,它尝试调用
到_ary
。例如,
s='helloworld';定义s.to_ary;分裂end
允许通过
a,b=s
分配单词。令人惊讶的是,在Ruby的一年中,您从未见过这种情况。例如,当迭代一个散列并使用两个块变量来分隔键和值而不是一个两元素数组(
hash.each{k,v{124;…}
而不是
hash.each{arr{124;…}
时,就会发生这种情况。顺便说一句:
one,two,three,[*rest=[*1..10]
@MichaelKohl我一直以为它是用args[0]和args[1]获得的,但这更有意义!谢谢!@MichaelKohl:是占位符吗?我从来没有在这种情况下见过它。我只从irb知道它,与上一个结果相同。它的基本意思是“我不在乎这个”。您知道如何在变量名前面加上
,表示您不打算在不触发警告的情况下使用结果(例如
\u foo
)这是一样的,只是没有名字。此外,它允许您交换变量而不需要第三个:
a,b=b,a
文档没有提到数组分解也会隐式发生(即没有括号),如果右侧只有一个值:
a,b=[1,2]
的工作方式类似于
(a,b)=[1,2]
。谢谢你的提醒!我不得不使用术语“分解”,并添加了一个嵌套分解的示例(在撰写本文时已向Clojure公开)。此外,如果您认为其中缺少某些内容,请随意修改。
(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]}