在Ruby中使用带有splats的下划线

Jam*_*ond 4 ruby ruby-on-rails splat

我已经 通过Ruby样式指南跟踪了Ruby的"为什么(Poignant)指南",以及Ruby教程如何思考.但这是我第一次看到尾随下划线.这些是什么东西?它们是否有用,如果是,我们何时使用它们以及如何将它们与splat运算符一起使用?

(Ruby样式指南链接锚定到实际示例)

7st*_*tud 8

合法变量名称是_.*_类似的东西*x.术语尾随下划线变量实际上是指赋值语句左侧的逗号分隔变量系列中的最后一个变量名称,例如:

a, b, _ = [1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

splat运算符有两个用途:

  1. 将数组分解为各个项目.
  2. 将项目收集到一个数组中.

发生了哪些取决于使用splat运算符的上下文.

以下是Ruby样式指南所说的不好的示例:

a, b, _ = *foo
Run Code Online (Sandbox Code Playgroud)

该示例中的尾随下划线变量是不必要的,因为您可以将前两个元素分配给foo变量ab通过编写:

a, b = *foo
Run Code Online (Sandbox Code Playgroud)

下划线变量用于说,我不关心这个变量,因此在那个例子中没有必要你想要做的就是分配给ab.

这个例子也可能被认为是糟糕的风格,因为*也不需要运营商(信用:Cary Swoveland):

a, b = [1, 2, 3]
p a, b

--output:--
1
2
Run Code Online (Sandbox Code Playgroud)

* 可以在右手边这样良好的效果可以使用:

x, y, z = 10, [20, 30]
p x, y, z

--output:--
10
[20, 30]
nil

x, y, z = 10, *[20, 30]
p x, y, z

--output:--
10
20
30
Run Code Online (Sandbox Code Playgroud)

所以,请记住,在样式指南的其他示例中,*右侧是多余的.

下一个例子是:

a, _, _ = *foo
Run Code Online (Sandbox Code Playgroud)

这是一个更具体的例子:

a, _, _ = *[1, 2, 3, 4]
p a, _

puts "-" * 10

a, _ = *[1, 2, 3, 4]
p a, _

--output:--
1
3
----------
1
2
Run Code Online (Sandbox Code Playgroud)

下面显示了分配在示例的第一部分中的工作方式:

 a, _, _
 ^  ^  ^
 |  |  |
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

在任何情况下,如果你摆脱左边的第二个下划线变量,那么a将被赋予相同的东西.如何摆脱两个下划线变量?

a = *[1, 2, 3, 4]
p a

--output:--
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

不.所以左边的第一个下划线变量似乎是必要的.但是,还有另一种语法可以在不使用尾随下划线变量的情况下获得相同的结果:

a, = *[1, 2, 3, 4]
p a

--output:--
1
Run Code Online (Sandbox Code Playgroud)

因此,第三个例子:

a, *_ = *foo
Run Code Online (Sandbox Code Playgroud)

也可以写成:

a, = *foo 
Run Code Online (Sandbox Code Playgroud)

从而避免尾随下划线变量.

最后,风格指南提供了这个神秘的建议:

当在赋值的左侧定义了splat变量并且splat变量不是下划线时,必须使用尾随下划线变量.

我认为这可能是指这样的事情:

*a = *[1, 2, 3, 4]
p a

--output:--
[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

如果要a分配数组的前三个元素,则必须编写:

*a, _ = *[1, 2, 3, 4]
p a

--output:--
[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

无论出于何种原因,解析器无法处理:

*a, = *[1, 2, 3, 4]

--output:--
*a, = *[1, 2, 3, 4]
     ^
1.rb:6: syntax error, unexpected '\n', expecting :: or '[' or '.'
Run Code Online (Sandbox Code Playgroud)

这是一个很好的例子:

*a, b, _ = *foo
Run Code Online (Sandbox Code Playgroud)

如果要将第二个元素分配给foo的最后一个元素,则必须使用尾随下划线变量b.

以下好例子有点令人困惑:

a, _b = *[1, 2, 3, 4]
a, _b, = *[1, 2, 3, 4]
Run Code Online (Sandbox Code Playgroud)

我们来试试吧:

a, _b = *[1, 2, 3, 4]
p a, _b

puts "-" * 10

a, _b, = *[1, 2, 3, 4]
p a, _b

--output:--
1
2
----------
1
2
Run Code Online (Sandbox Code Playgroud)

在ruby中,变量名称与_b名为_or 的变量没有区别b.在功能性语言,如二郎,变量__BB有不同的效果-但不是在Ruby中.

顺便说一下,我不会花五分钟学习这种风格 - 这太深奥了.

  • 哇!这是一次非常强大的巡回演出.我猜你没有想到你的答案在你开始写作的时候差不多长而且意义深远.你注意到如果`a,=*[1,2,3,4]`导致`a#=> 1`.我可能在你的答案中错过了它,但是当你移除splat时会得到相同的结果.通常看到`a,_ = [1,2,3,4]`,但事实上只需要逗号. (2认同)