鸭子字符串,符号和数组的优雅方式?

Bry*_*sen 5 ruby

这是针对我不能破解的现有公共API,但我确实希望扩展.

目前,该方法采用字符串或符号或其他任何在作为第一个参数传递时有意义的内容 send

我想添加发送字符串,符号等列表的功能.我可以使用is_a? Array,但还有其他方式发送列表,这不是非常ruby-ish.

我会打电话map给名单,所以第一个倾向是使用respond_to? :map.但是字符串也会响应:map,因此无法正常工作.

Jam*_*sen 6

如何将它们全部视为Arrays?您希望Strings 的行为与Array仅包含该行为的行为相同String:

def foo(obj, arg)
  [*arg].each { |method| obj.send(method) }
end
Run Code Online (Sandbox Code Playgroud)

这个[*arg]技巧很有效,因为splat operator(*)将单个元素转换为自身或者Array转换为元素的内联列表.

后来

这基本上只是一个语法上加糖的版本或Arnaud的答案,尽管如果你传递一个Array包含其他的Arrays 会有微妙的差异.

后来还是

foo返回值有关的另外一个区别.如果你打电话foo(bar, :baz),你可能会惊讶地[baz]回来.要解决此问题,您可以添加红隼:

def foo(obj, arg)
  returning(arg) do |args|
    [*args].each { |method| obj.send(method) }
  end
end
Run Code Online (Sandbox Code Playgroud)

它将始终返回arg.或者你可以这样做returning(obj),你可以链接电话foo.这取决于你想要什么样的回报价值行为.