use*_*029 10 ruby parameters parameter-passing
我有一堆函数可以接受一个对象数组,或者一个对象被设计为一个包含一个对象的数组,我正在寻找一种更简洁的方法来完成它.基本上,我想知道如何使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
Run Code Online (Sandbox Code Playgroud)
任何帮助将不胜感激!谢谢.
Nik*_*ola 22
我发现最干净的解决方案是使用内核方法Array:
Array(5) #=> [5]
Array([1, 2, 3]) #=> [1,2,3]
Run Code Online (Sandbox Code Playgroud)
所以
def foo(bar_or_bars)
bars = Array(bar_or_bars)
bars.each { |baz| ... }
Run Code Online (Sandbox Code Playgroud)
这甚至可以在具有数组作为元素的嵌套数组上工作(它们不会被展平)
Nik*_* B. 13
你要做的第一件事就是把unless逻辑编写成一行:
bars = bar_or_bars.is_a?(Array) ? bar_or_bars : [bar_or_bars]
Run Code Online (Sandbox Code Playgroud)
如你所见,我在这里给它一个新名称,因为它不再是一个酒吧或酒吧,它现在绝对是一个集合.
这个和你原来的方法的问题在于,尽管你的函数可以在任何函数上运行Enumerable,但是你会强迫你的用户给你一个特定类型的参数,这会破坏鸭子的输入.
部分解决该问题的巧妙方法如下:
def foo(bar_or_bars)
bars = [*bar_or_bars]
bars.each { |baz| ... }
end
Run Code Online (Sandbox Code Playgroud)
不过,我不会完全称之为可读.它实际上闻起来很像糟糕的API设计.可能你应该更好地采取这样的多个参数:
def foo(*bars)
bars.each { |baz| ... }
end
Run Code Online (Sandbox Code Playgroud)
让调用者决定是否要传递单个对象或数组:
foo("XYZ")
ary = ["abc", "def"]
foo(*ary)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3900 次 |
| 最近记录: |