带双括号参数的Ruby方法

时间:2019-02-08 00:52:46

标签: ruby methods parameters

我在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)

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

2 个答案:

答案 0 :(得分:8)

解构。

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,因为单值数组在多值赋值中会自动解构)作为解构的另一个示例。

答案 1 :(得分:8)

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

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