我希望能够使用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中实现?
答案 0 :(得分:8)
在下面的示例中,lambda仍然是匿名的,但它有一个引用。 (这会传递匿名吗?)
(l = lambda { l.call }).call
(感谢Niklas B.指出我原来答案中的错误;我只在IRB中进行了测试,并在那里工作过。)
这当然以SystemStackError: stack level too deep
错误结束,但它证明了目的。
答案 1 :(得分:5)
似乎匿名函数确实没有任何参考。您可以按callee
进行检查lambda{ __callee__ }.call #=> nil
如果没有参考,你就无法调用此功能。 我可以向你推荐一个更干净的变种:
(fac = lambda{ |n| n==1 ? 1 : n*fac.call(n-1) }).call(5)
答案 2 :(得分:1)
除了KL-7's comment之外,这里还有一个Y组合解决方案:
/* -cancel returns immediately, but marks a task as being canceled.
* The task will signal -URLSession:task:didCompleteWithError: with an
* error value of { NSURLErrorDomain, NSURLErrorCancelled }. In some
* cases, the task may signal other work before it acknowledges the
* cancelation. -cancel may be sent to a task that has been suspended.
*/
您通常会拆分这些:
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
,但它不会在lambda中使用。
我使用Ruby的fac
语法和->
代替.()
:
.call()
使用curry
:
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
调用
y
答案 3 :(得分:1)
fact = -> (x){ x < 2 ? 1 : x*fact.(x-1)}
最小功能