【问题标题】:Ruby method with parameters in double parenthesis带有双括号参数的 Ruby 方法
【发布时间】:2019-07-02 05:39:35
【问题描述】:

我在 erb 库中遇到过以下代码。注意双(( ))

class MyTest
  def location=((filename, lineno))
    @filename = filename
    @lineno = lineno if lineno
  end
end

下面的locatia=方法是另一个版本,没有(( ))进行测试:

class MyTest    
  def locatia=(filename, lineno)
    @filename = filename
    @lineno = lineno if lineno
  end
end

我得到了这个结果:

a = MyTest.new
a.location = "foo", 34
a # => #<MyTest:0x2a2e428 @filename="foo", @lineno=34>

b = MyTest.new
b.location = "foo"
b # => #<MyTest:0x2a2e338 @filename="foo">

c = MyTest.new
c.locatia = "foo", 34
c # >> `locatia=': wrong number of arguments (given 1, expected 2) (ArgumentError)

带双括号的版本可以正常工作。单人失败。它必须在源代码的某个级别上指定。有什么线索吗?

【问题讨论】:

    标签: ruby methods parameters


    【解决方案1】:

    解构。

    location= 接受一个参数。这个参数被假定为一个数组,并且被解构,使得数组的第一个元素进入filename,第二个进入lineno。外括号是方法定义的普通(通常是可选的)括号;内括号表示第一个(也是唯一一个)参数的结构。

    下面是另一个在工作中解构的例子:

    { foo: 17, bar: 34 }.each.with_index { |(key, value), index|
      p [key, value, index]
    }
    # => [:foo, 17, 0]
    #    [:bar, 34, 1]
    

    Hash#each 生成对 [key, value]; Enumerator#with_index 生成一对 [value, index]。将它们都应用,你会得到[[key, value], index] 传递给块。我们可以这样做:

    { foo: 17, bar: 34 }.each.with_index { |pair, index|
      key = pair[0]
      value = pair[1]
      p [key, value, index]
    }
    

    但是解构要简单得多。我们甚至可以写(key, value) = pair(或key, value = pair,因为单右值数组在多左值赋值中自动解构)作为解构的另一个示例。

    【讨论】:

    【解决方案2】:

    在生产代码中看到这一点有点不寻常,但这里发生的是参数列表中的列表扩展

    def location=((filename, lineno))
    end
    

    这意味着你这样称呼它:

    x.location = 1,2
    

    那些被扩展成两个独立参数的地方。 mutator 方法只能接受一个参数,但该参数可以是一个列表,您可以将该参数扩展为多个值。

    通常你会在迭代器中看到这一点:

    { a: 'b', c: 'd' }.each_with_index.map do |(k,v), i|
      # k, v come in as a pair, i is separate
    end
    

    虽然这样也很少见。

    其他情况也可以看到:

    a = [ 1, 2 ]
    b = 3
    
    # Without list expansion, just one-to-one assignment
    x, y, z = a, b
    # x => [ 1, 2 ]
    # y => 3
    # z => nil
    
    # With list expansion
    (x, y), z = a, b
    # x => 1
    # y => 2
    # z => 3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-26
      • 2022-08-10
      • 2010-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多