标记未使用的块变量

时间:2011-12-31 17:57:30

标签: ruby variables block

当存在不使用的块或局部变量时,有时人们会将其标记为*,有时标记为_

{[1, 2] => 3, [4, 5] => 6}.each{|(x, *), *| p x}

{[1, 2] => 3, [4, 5] => 6}.each{|(x, _), _| p x}

{[1, 2, 3], [4, 5, 6]}.each{|*, x, *| p x}

{[1, 2, 3], [4, 5, 6]}.each{|_, x, _| p x}

def (x, *), *; p x; end

def (x, _), _; p x; end

def *, x, *; p x; end

def _, x, _; p x; end

它们之间有什么区别,我什么时候应该使用哪种?当需要将多个变量标记为未使用时,如上例所示,是否更好?

4 个答案:

答案 0 :(得分:31)

*表示“所有剩余参数”。 _只是另一个变量名,虽然它有点特殊。所以他们是不同的,例如以下没有意义:

[[1, 2, 3], [4, 5, 6]].each{|*, x, *| p x}  # 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

现在_ 指定的变量名称,以便在您不想使用值时使用。它是一个特殊的变量名,原因有两个:

  1. 如果您不使用它(如果警告已启用),Ruby将不会抱怨
  2. Ruby允许您在参数列表中重复它。
  3. 第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
    

答案 1 :(得分:1)

我认为这主要是风格和程序员的选择。在Ruby中使用*对我来说更有意义,因为它的目的是累积从该位置向前传递的所有参数。 _是一个很难看到在Ruby中使用的残留变量,我听说它需要消失。所以,如果我要使用其中任何一个,我会使用*

有些公司可能会在他们的编程风格文档中定义它,如果他们有一个,但我怀疑它的大部分时间是值得的,因为它是一个抛弃变量。我已经专业发展了20多年,从来没有看到任何定义扔掉命名的东西。

就个人而言,我并不担心这一点,我更关注单字母变量的使用。我会使用unusedvoidblackhole来实现此目的。

答案 2 :(得分:1)

它们之间有什么区别?

_案例中,正在创建局部变量_。这就像使用x但名称不同。

*案例中,将表达式分配给*会创建[expression]。我不太确定它有什么用处,因为它似乎没有做任何用括号括起来的表达式。

我什么时候应该使用哪个?

在第二种情况下,您最终不会创建额外的符号,但对于解释器来说,它看起来稍微有些工作。此外,很明显你永远不会使用那个结果,而使用_,你必须阅读循环以了解它是否被使用。

但是我预测你的代码质量将取决于你用来摆脱未使用的块参数的技巧。 *确实有某种模糊不清的酷因素。

注意:在尝试此操作时,请注意,在irb中,_保存最后一个表达式的值。

答案 3 :(得分:1)

IMO这种做法使代码的可读性降低,而且不那么明显。

特别是在采用块的API方法中,可能不清楚块实际需要什么。这故意从信息源中删除信息,使维护和修改变得更加困难。

我宁愿将变量命名为恰当的;在一个短的区块中,很明显它没有被使用。在较长的区块中,如果非使用非常显着,则可以详细说明原因。