我希望能够使用Ruby从其内部调用匿名lambda。考虑下面的递归块(返回阶乘)。我知道我可以将它赋给一个变量,而该变量在lambda的作用域内:
fac = lambda { |n| n == 1 ? 1 : n * fac.call(n - 1) }
fac.call(5)
但是,我希望能够做到以下几点(到目前为止还没有实际原因,我只是对进一步探索这门语言感兴趣):
(lambda { |n| n == 1 ? 1 : n * self.call(n - 1) }).call(5)
我知道这是行不通的,因为self
是main
对象。我做错了吗?我是否正在尝试做一些不可能的事情--如果不是,这是因为一些理论上的限制还是仅仅没有在Ruby中实现?
发布于 2012-03-01 21:54:05
在下面的示例中,lambda仍然是匿名的,但它有一个引用。(这算是匿名吗?)
(l = lambda { l.call }).call
(感谢Niklas B.指出了我原始答案中的错误;我只在IRB中测试了它,它在那里工作)。
当然,这以SystemStackError: stack level too deep
错误结束,但它演示了目的。
发布于 2019-04-23 01:24:08
fact = -> (x){ x < 2 ? 1 : x*fact.(x-1)}
极小函数
发布于 2015-12-15 00:43:18
除了KL-7's comment之外,这里还有一个Y组合子解决方案:
lambda { |f|
lambda { |x| x.call(x) }.call(
lambda { |x| f.call( lambda { |v| x.call(x).call(v) } ) } )
}.call(
lambda { |f|
lambda { |n| n == 0 ? 1 : n * f.call(n - 1) }
}
).call(5) #=> 120
您通常会将以下内容拆分:
y = lambda { |f|
lambda { |x| x.call(x) }.call(
lambda { |x| f.call( lambda { |v| x.call(x).call(v) } ) } )
}
fac = y.call(
lambda { |f| lambda { |n| n == 0 ? 1 : n * f.call(n - 1) } }
)
fac.call(5) #=> 120
请注意,尽管分配了fac
,但它不会在lambda中使用。
我会使用Ruby语言的->
语法和.()
,而不是.call()
y = ->(f) {
->(x) { x.(x) }.(
->(x) { f.(->(v) { x.(x).(v) }) } )
}
fac = y.(->(f) {
->(n) { n == 0 ? 1 : n * f.(n - 1) }
})
fac.(5) #=> 120
通过使用curry
,可以稍微简化y
调用
y = ->(f) {
->(x) { x.(x) }.(
->(x) { f.curry.(->(v) { x.(x).(v) }) } )
}
fac = y.(
->(f, n) { n == 0 ? 1 : n * f.(n - 1) }
)
fac.(5) #=> 120
https://stackoverflow.com/questions/9516061
复制相似问题