1

我想定义一个可以采用可选数量的参数和散列的方法,就像这样

def foo(*b, **c)
  2.times.map.with_index { |i|
    new_hash, new_array = {}, b
    c.map { |key, value| new_hash[key] = value[i] unless value[i].nil? }
    new_array << new_hash if new_hash.length > 0
    send(:bar, new_array)
  }
end

def bar(*b)
  p b
end

如果我正确理解了 splat 和 double splat 运算符(我对此表示怀疑),那么这应该将数组发送b到方法,并且只有在它包含某些内容bar时才添加new_hashfrom 。foo但是,发生了一些奇怪的事情 - 我将尝试用下面的一些片段来说明

# invoking #foo 
foo(a, key: 'value')

# first iteration of loop in #foo
  # i is 0
  # b is []
  # c is { :key => ['value1'] }
  # send(:bar, new_array) => send(:bar, [{:key => 'value1'}])
  # bar yields: [{:key => 'value1'}]

然而,现在发生了一些事情

# second iteration of loop in #foo
  # i is 1
  # b is [:key => 'value1'] <---- why?
  # c is { :key => ['value1']

b为什么的 循环内的值发生了变化foo

编辑更新了代码以反映为每次迭代创建一个新数组

4

1 回答 1

2
new_hash, new_array = {}, b

这不会创建b. 现在new_arrayb指向同一个对象。就地修改一个将修改另一个。

new_array << new_hash

这会在原地修改new_array(并因此b),因此新元素将保留在下一次迭代中。使用类似的东西+,它会创建一个副本:

send(:bar, *(b + (new_hash.empty? ? [] : [new_hash])))
于 2014-10-17T12:52:23.370 回答