【问题标题】:Marking an unused block variable标记未使用的块变量
【发布时间】:2011-12-31 17:57:29
【问题描述】:

当有不使用的块或局部变量时,有时人们用*标记它,有时用_标记。

{[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

它们之间有什么区别,我应该什么时候使用?当需要像上面的例子一样将多个变量标记为未使用时,哪个更好?

【问题讨论】:

    标签: ruby variables block


    【解决方案1】:

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

    [[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(如果出现警告),Ruby 不会抱怨
    2. 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
    

    【讨论】:

    • 感谢您的详细回答。这个答案包含我想要的所有信息。
    【解决方案2】:

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

    一些公司可能会在他们的编程风格文档中定义它,如果他们有的话,但我怀疑它是否值得他们花费大部分时间,因为它是一个一次性变量。我从事专业开发已有 20 多年,从未见过任何定义一次性物品命名的东西。

    就我个人而言,我不担心这一点,我更关心单字母变量的使用。为此,我会使用unusedvoidblackhole 而不是其中任何一个。

    【讨论】:

    • _不会消失并有特定的治疗,请参阅我的回答。此外,在警告中运行 Ruby 可能会在使用 unused 或 simial 时给您警告,但在使用 _ 时不会;也看看我的回答;-)
    【解决方案3】:

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

    特别是在 API 方法中,可能不清楚该块实际期望什么。这故意从源中删除信息,使维护和修改更加困难。

    我宁愿对变量进行适当的命名;在很短的时间内,很明显它没有被使用。在较长的块中,如果不使用是显着的,可以在评论中详细说明原因。

    【讨论】:

      【解决方案4】:

      它们之间有什么区别?

      _ 的情况下,正在创建一个局部变量_。这就像使用x,但名称不同。

      * 的情况下,将表达式分配给* 会创建[expression]。我不太确定它有什么用,因为它似乎并没有做任何只是用括号括起来的表达式。

      什么时候应该使用哪个?

      在第二种情况下,您最终不会创建一个额外的符号,但看起来解释器的工作量要多一些。此外,很明显,您永远不会使用该结果,而对于 _,您必须阅读循环才能知道它是否被使用。

      但我预测您的代码质量将取决于其他因素,而不是您使用哪种技巧来摆脱未使用的块参数。 * 确实有一些我喜欢的晦涩的酷因素。

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

      【讨论】:

      • 您的意思是** 还是*?我的意思是*,但它们有什么不同吗?我知道* 的用法是在为变量名添加前缀时创建一个数组,但是* 的单独使用是否相同?而在主环境中,如果我输入* = ['a'],它会返回['a']。这是什么意思?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      相关资源
      最近更新 更多