所以只是为了好玩(并且为了证明只要付出一点努力,在 ruby 中几乎任何事情都是可能的)我们可以在 Symbol(我们称之为 Symbol#chain)上定义一个方法来提供这个功能还有一点
class Symbol
def proc_chain(*args)
args.inject(self.to_proc) do |memo,meth|
meth, *passable_args = [meth].flatten
passable_block = passable_args.pop if passable_args.last.is_a?(Proc)
Proc.new do |obj|
memo.call(obj).__send__(meth,*passable_args,&passable_block)
end
end
end
alias_method :chain, :proc_chain
end
然后可以这样调用
[:a, :b, :c].map(&:to_s.chain(:upcase))
#=> ["A","B","C"]
# Or with Arguments & blocks
[1,2,3,4,5].map(&:itself.chain([:to_s,2],:chars,[:map,->(e){ "#{e}!!!!"}]))
#=> => [["1!!!!"], ["1!!!!", "0!!!!"], ["1!!!!", "1!!!!"],
# ["1!!!!","0!!!!", "0!!!!"], ["1!!!!", "0!!!!", "1!!!!"]]
甚至可以单独使用
p = :to_s.chain([:split,'.'])
p.call(123.45)
#=> ["123","45"]
# Or even
[123.45,76.75].map(&p)
#=> => [["123", "45"], ["76", "75"]]