2012-02-28 88 views
9

我有一大堆函数可以接受一个对象数组,或者一个对象被设计为一个包含一个对象的数组,我正在寻找一个更清洁的方式来实现这一点基本上,我想知道我怎么能做出unless部分在以下功能更简洁:接受作为单个对象或对象数组的参数

def foo(bar_or_bars) 
    unless bar_or_bars.is_a?(Array) 
    bar_or_bars = [bar_or_bars] 
    end 
    bar_or_bars.each { |baz| ... } 
end 

任何帮助将不胜感激!谢谢。

回答

11

你可以做的第一件事就是写unless逻辑一行:

bars = bar_or_bars.is_a?(Array) ? bar_or_bars : [bar_or_bars] 

正如你看到的,我给它一个新的名字在这里,因为它不再是一个或多个杆,它现在绝对是一个集合。

这和你原来的方法的问题是,虽然你的功能可以在任何Enumerable工作,你会强迫你的用户给你一个特定类型的参数,这打破了鸭子打字。

一个绝招来部分地解决这个问题是这样的:

def foo(bar_or_bars) 
    bars = [*bar_or_bars] 
    bars.each { |baz| ... } 
end 

我不完全称之为可读,虽然。它实际上闻起来很像糟糕的API设计。也许你应该更好地利用多个参数是这样的:

def foo(*bars) 
    bars.each { |baz| ... } 
end 

而让来电者决定是否要通过单个对象或数组:

foo("XYZ") 
ary = ["abc", "def"] 
foo(*ary) 
+0

谢谢,第二招是我一直在寻找。我知道它并不理想,但实际上我已经简化了一些:因为我有许多连续的参数,其行为与我描述的相似,所以我无法在参数列表中使用普通的旧splat。 – user2398029 2012-02-28 03:20:54

18

我发现是使用最简洁的解决方案内核方法阵列:

Array(5) #=> [5] 
Array([1, 2, 3]) #=> [1,2,3] 

所以

def foo(bar_or_bars) 
    bars = Array(bar_or_bars) 
    bars.each { |baz| ... } 

这甚至会在具有数组作为元素嵌套数组工作

1

我目前使用这个(他们不会变平):

bars = [bar_or_bars].flatten 
相关问题