在Ruby中,如果我有n个函数:
def a puts "a" end def b puts "b" end
有没有什么方法可以像
[a,b].each do |x| puts "running #{x.name} run a end
我的一个想法是,我可以注册一个函子数组或其他东西,或者lambda可以帮助?谢谢你的帮助,凯文
lawou6xi1#
在Ruby中,def关键字定义了一个对象方法而不是函数。Ruby中最接近函数的是块、procs和lambda表达式,但“函数”在Ruby中并不是真正的一流概念。方法存在于一个对象上,但是如果你在顶级命名空间中声明它们(例如在类的外部),那么它们会被附加到一个特殊的顶级绑定中,这个绑定的作用 * 有点 * 像一个全局命名空间。这不是,真的,但是当试图从其他语言中推理Ruby时,这是一个有用的类比。此外,当你定义一个方法时,Ruby会为该方法返回一个Symbol。你可以在定义方法时在交互式REPL(如irb)中看到这一点,因为Ruby在定义方法时会返回一个Symbol。虽然有一些方法可以以String的形式调用方法名,但Ruby在内部将方法和类名存储为Symbol对象,所以这就是我将要演示的内容。例如:
def
def a puts "a" end #=> :a
有了这些知识,就很容易迭代一组存储为Symbol对象数组的方法,并使用Object#send调用它们中的每一个。例如:
def a p "a" end def b p "b" end [:a, :b].each { send _1 } #=> [:a, :b]
虽然它为每个方法返回Symbol,但它也会将您期望的字符打印到终端:“一个”“B”请注意,#puts总是返回nil,所以当你想 * 返回 * 通过迭代你的集合而不是简单地将它们发送到终端而生成的值时,使用内核#p更有意义。如果你宁愿返回[nil, nil],那么继续使用#puts代替。此外,使用#map而不是#each与Kernel#p一起使用,每次迭代都会返回一个字母而不是Symbol,所以要注意区别。期望一个而得到以下结果可能会令人困惑:
[nil, nil]
[:a, :b].map { send _1 } # => ["a", "b"]
这是因为#each返回原始Array,而#map返回在每个元素上Map块的结果。它们非常相似,但如果不小心,细微的差异可能会让你绊倒。
如果你真的想保持你原来的语义,那么就这样称呼它:
["a", "b"].map do |x| puts "running method #{x}" send x end
这不太符合习惯,而且可能会让人感到困惑,因为你并没有真正使用字符或String对象,但无论你使用#each还是#map,都会得到一个String。尽管如此,它会打印并返回:
running method a "a" running method b "b" #=> ["a", "b"]
正如你所料
mm5n2pyu2#
使用Lambda:
[ -> () { p "a" }, -> () { p "b" } ].each do |proc| proc.() end
2条答案
按热度按时间lawou6xi1#
Call Object#send on a Array of Symbols
在Ruby中,
def
关键字定义了一个对象方法而不是函数。Ruby中最接近函数的是块、procs和lambda表达式,但“函数”在Ruby中并不是真正的一流概念。方法存在于一个对象上,但是如果你在顶级命名空间中声明它们(例如在类的外部),那么它们会被附加到一个特殊的顶级绑定中,这个绑定的作用 * 有点 * 像一个全局命名空间。这不是,真的,但是当试图从其他语言中推理Ruby时,这是一个有用的类比。
此外,当你定义一个方法时,Ruby会为该方法返回一个Symbol。你可以在定义方法时在交互式REPL(如irb)中看到这一点,因为Ruby在定义方法时会返回一个Symbol。虽然有一些方法可以以String的形式调用方法名,但Ruby在内部将方法和类名存储为Symbol对象,所以这就是我将要演示的内容。例如:
有了这些知识,就很容易迭代一组存储为Symbol对象数组的方法,并使用Object#send调用它们中的每一个。例如:
虽然它为每个方法返回Symbol,但它也会将您期望的字符打印到终端:
“一个”
“B”
请注意,#puts总是返回nil,所以当你想 * 返回 * 通过迭代你的集合而不是简单地将它们发送到终端而生成的值时,使用内核#p更有意义。如果你宁愿返回
[nil, nil]
,那么继续使用#puts代替。此外,使用#map而不是#each与Kernel#p一起使用,每次迭代都会返回一个字母而不是Symbol,所以要注意区别。期望一个而得到以下结果可能会令人困惑:
这是因为#each返回原始Array,而#map返回在每个元素上Map块的结果。它们非常相似,但如果不小心,细微的差异可能会让你绊倒。
保留原有语义
如果你真的想保持你原来的语义,那么就这样称呼它:
这不太符合习惯,而且可能会让人感到困惑,因为你并没有真正使用字符或String对象,但无论你使用#each还是#map,都会得到一个String。尽管如此,它会打印并返回:
正如你所料
mm5n2pyu2#
使用Lambda: