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

Use of underscores with splats in Ruby

我关注 Why's (Poignant) Guide to Ruby, through couple of other guides, to Ruby style guide 以了解 Ruby 主义者的想法。 但这是我第一次看到 尾随下划线 。这些是什么?它们有用吗?如果有用,我们什么时候使用它们以及我们如何将它们与 splat 运算符一起使用?

(Ruby 风格指南 link 锚定到实际示例)

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

a, b, _ = [1, 2, 3, 4]

splat 运算符有两个用途:

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

其中哪一个发生取决于使用 splat 运算符的 上下文

以下是 Ruby 风格指南所说的 不好的例子:

a, b, _ = *foo

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

a, b = *foo

下划线变量用来表示,我不关心这个变量,因此如果你只想赋值,那么在那个例子中没有必要到 ab

该示例也可能被认为是 糟糕的 样式,因为也不需要 * 运算符(来源:Cary Swoveland):

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

--output:--
1
2

*可以用在右手边效果好,像这样:

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

因此,请记住,在样式指南的其余示例中,右侧的 * 是多余的。

下一个不好的例子是:

a, _, _ = *foo

这是一个更具体的例子:

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

puts "-" * 10

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

--output:--
1
3
----------
1
2

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

 a, _, _
 ^  ^  ^
 |  |  |
[1, 2, 3, 4]

无论如何,如果去掉左边的第二个下划线变量,那么a将被赋值相同的东西。去掉两个下划线变量怎么样?

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

--output:--
[1, 2, 3, 4]

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

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

--output:--
1

因此,第三个不好例子:

a, *_ = *foo

也可以写成:

a, = *foo 

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

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

Trailing underscore variables are necessary when there is a splat variable defined on the left side of the assignment, and the splat variable is not an underscore.

我想这可能是指这样的事情:

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

--output:--
[1, 2, 3, 4]

如果你想让a被赋值为数组的前三个元素,那么你要这样写:

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

--output:--
[1, 2, 3]

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

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

--output:--
*a, = *[1, 2, 3, 4]
     ^
1.rb:6: syntax error, unexpected '\n', expecting :: or '[' or '.'

这是一个很好的例子:

*a, b, _ = *foo

尾部下划线变量是必需的,如果你想将 foo 的第二个到最后一个元素分配给 b

下面的好例子有点令人费解:

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

让我们试试看:

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

在ruby中,变量名如_b与变量名_b没有区别。在像 Erlang 这样的函数式语言中,变量 __B 以及 B 有不同的效果——但在 Ruby.

中没有

顺便说一句,我不会花五分钟来学习那种风格——它太深奥了。

在变量前加上下划线 _ 没有任何语法意义,它只是一个约定(即,它不是一个严格的规则,并且总是可以在不破坏代码的情况下被破坏)。

它在 Ruby 中不常使用,但它在 Ruby 中对应于在 LaTeX 编程中使用 at 标记 @ 前置函数。据我理解,它用于表示"inferior"、"sub-routine"、"core"或"element"等概念。可以认为是"pluralization".

的反义词

例1.数组的变量名复数是很常见的,数组的元素要用单数名来引用:

items = [1, 2, 3]
items.each{|item| ...}

这可能有点奇怪,但即使在使用非单词变量名引用元素时也偶尔会看到这种做法:

is = [1, 2, 3]
is.each{|i| ...}

现在,假设预先用单数命名了数组,然后你想从中区分元素名称。在这种情况下,您可以在元素名称前加上下划线:

item = [1, 2, 3]
item.each{|_item| ...}

x = [1, 2, 3]
x.each{|_x| ...}

示例 2。假设您有一个调用另一个的方法,而后者仅用作子例程,并且完成前者所做的大部分工作。在这种情况下,您可以在后者前面加上下划线:

def foo a, b
  ... # Do something just a bit here
  _foo(a, b)
end
def _foo a, b
  ... # Do still a bit here
  __foo(a, b)
end
def __foo a, b
  ... # Most of the job is done here
end

示例 3。这有点不同,因为它是硬编码 Ruby 的一部分,它使用两个下划线(而不是一个),并且围绕变量(而不是前置)。有方法 send,调用 __send__。这样一来,即使 send 被重新定义为其他内容,也可以使用 __send__