我正在修补 Array 以添加我自己的方法Array#left_outer_join
。因为我是 Ruby 新手,所以我想做一些漂亮的事情,并且有一个方法可以返回一个新数组和一个 bang 方法来替换我当前的数组。然而,我最终编写了两次相同的代码,非爆炸和爆炸方法之间的唯一区别是调用 map 或 map!分别。
我已经阅读了一些关于块和元编程的内容,最后得到了以下内容:
class Array
def left_outer_join_proc(method, ary, &block)
self.send(method) do |obj1|
ary.each do |obj2|
if yield obj1, obj2
obj2.keys.each do |key|
obj1[key] = obj2[key]
end
break
end
end
obj1
end
end
def left_outer_join(ary, &block)
left_outer_join_proc(:map, ary, &block)
end
def left_outer_join!(ary, &block)
left_outer_join_proc(:map!, ary, &block)
end
end
events.left_outer_join!(users) {|event, user| event['user_id'] == user['user_id'] }
到目前为止,这工作得很好,Object.send
是(根据 SO)动态调用方法的最佳用途,我有点喜欢这种方法(尽管我的纯粹主义者讨厌Array
用第三种方法污染类)。
现在的问题是:定义非爆炸和爆炸方法并使其保持干燥的最佳实践是什么?
编辑:这个问题不是关于“爆炸方法是否意味着破坏性方法?” 但实际上是关于“如果我要写Array#add_two
and Array#add_two!
,如何确保我不必定义一个方法 withmap{|x| x +2 }
和另一个 with map!{|x| x + 2 }
.
我知道我可以使用
def add_two!(x)
self = add_two(x)
end
但我要求的是“最佳性能、最佳可读性”类型的答案(查看源代码并Array#map
查看Array#map!
“细微”的性能差异)。