标记未使用的块变量
当存在不使用的块或局部变量时,有时人们用*
标记它,有时用_
标记。
{[1, 2] => 3, [4, 5] => 6}.each{|(x, *), *| px} {[1, 2] => 3, [4, 5] => 6}.each{|(x, _), _| px} {[1, 2, 3], [4, 5, 6]}.each{|*, x, *| px} {[1, 2, 3], [4, 5, 6]}.each{|_, x, _| px} def (x, *), *; px; end def (x, _), _; px; end def *, x, *; px; end def _, x, _; px; end
他们之间有什么区别,我什么时候应该使用哪个? 当需要将多个变量标记为未使用时,如上例所示,是否更好?
A *
表示“所有剩余参数”。 _
只是另一个变量名,虽然它有点特殊。 所以它们是不同的,例如以下没有意义:
[[1, 2, 3], [4, 5, 6]].each{|*, x, *| px} # Syntax error
确实,Ruby应该知道第一颗星是否应该得到0,1或2的值(反之)?
在极少数情况下,您希望使用星形来忽略参数。 例如,如果您只想使用可变数量的参数中的最后一个:
[[1], [2, 3], [4, 5, 6]].each{|*, last| p last} # => prints 1, 3 and 6
Ruby允许你不给参数的“其余”命名,但你可以使用_
:
[[1], [2, 3], [4, 5, 6]].each{|*_, last| p last} # => prints 1, 3 and 6
通常,参数的数量是已知的,您最好的选择是使用_
:
[[1, 2, 3], [4, 5, 6]].each{|_, mid, _| p mid} # prints 2 and 5
请注意,您也可以将最后一个参数保留为未命名(就像使用*
),尽管不太明显:
[[1, 2, 3], [4, 5, 6]].each{|_, mid, | p mid} # prints 2 and 5
现在_
是您不想使用值时使用的指定变量名。 它是一个特殊的变量名称,原因有两个:
- 如果您不使用Ruby,Ruby不会抱怨(如果警告已启用)
- Ruby允许您在参数列表中重复它。
第1点的例子:
> ruby -w -e "def foo; x = 42; end; foo" -e:1: warning: assigned but unused variable - x > ruby -w -e "def foo; _ = 42; end; foo" no warning
第2点的例子:
[[1, 2, 3], [4, 5, 6]].each{|unused, mid, unused| p mid} # => SyntaxError: (irb):23: duplicated argument name [[1, 2, 3], [4, 5, 6]].each{|_, mid, _| p mid} # => prints 2 and 5
最后,正如@DigitalRoss所说, _
在irb
保留最后的结果
更新 :在Ruby 2.0中,您可以使用以_
开头的任何变量来表示它未被使用。 这样,变量名称可以更明确地显示被忽略的内容:
_scheme, _domain, port, _url = parse_some_url # ... do something with port
我认为这主要是风格和程序员的选择。 在Ruby中使用*
对我来说更有意义,因为它的目的是累积从该位置向前传递的所有参数。 _
是一个在Ruby中很少见到的残留变量,我听说它需要消失。 所以,如果我要使用其中任何一个,我会使用*
。
有些公司可能会在他们的编程风格文档中定义它,如果他们有一个,但我怀疑它的大部分时间是值得的,因为它是一个丢失的变量。 我已经专业开发了20多年,并且从未见过任何定义扔掉命名的东西。
就个人而言,我并不担心这一点,我更关心单字母变量的使用。 为此,我会使用unused
或void
或blackhole
。
IMO这种做法使代码的可读性降低,而且不那么明显。
特别是在采用块的API方法中,可能不清楚块实际期望什么。 这故意从源中删除信息,使维护和修改更加困难。
我宁愿变量被恰当地命名; 在短暂的区块中,很明显它没有被使用。 在较长的区块中,如果非使用是显着的,评论可能会详细说明原因。
它们之间有什么区别?
在_
case中,正在创建局部变量_
。 这就像使用x
但命名不同。
在*
情况下,将表达式赋值给*
创建[expression]
。 我不太确定它有什么用处,因为它似乎没有做任何用括号括起来的表达式。
我什么时候应该使用哪个?
在第二种情况下,您最终不会创建额外的符号,但对于解释器来说,它看起来稍微有些工作。 此外,很明显你永远不会使用那个结果,而使用_
,必须阅读循环以了解它是否被使用。
但我预测你的代码质量将取决于你用来摆脱未使用的块参数的技巧。 *
确实有一些我不喜欢的模糊的酷因子。
注意:在尝试此操作时,请注意在irb中, _
保存最后一个表达式的值。