在 Ruby 中禁用递归以强制使用 Y Combinator
Disable Recursion in Ruby to Force Use of Y Combinator
Ruby的递归如何'sabotaged'禁用ruby方法进行递归的能力?
需要创建一个程序来教授 lambda 演算,但使用 Ruby。
来自 Crockford 的动机 JavaScript - https://www.youtube.com/watch?v=ya4UHuXNygM&feature=youtu.be&t=1h9m53s
您可以使用 TracePoint
API 来跟踪所有方法调用,并 returns 并构建堆栈以查看调用的方法是否已经在堆栈中。这样,您至少可以 检测 递归,然后您可以 raise
异常或 exit
程序。
类似于:
stack = []
TracePoint.trace(:call, :return) do |trace|
p trace, stack
method = trace.method_id
case trace.event
when :call
if stack.include?(method)
$stderr.puts "RECURSION DETECTED: method `#{stack.last}` calls method `#{method}`."
exit!
end
stack.push(method)
when :return
stack.pop
end
end
def foo; bar end
def bar; baz end
def baz; qux end
def qux; bar end
foo
请注意,我在其中插入了一个调试 p
rint,以便您可以观察它是如何工作的:
#<TracePoint:call `foo'@./test.rb:20>
[]
#<TracePoint:call `bar'@./test.rb:21>
[:foo]
#<TracePoint:call `baz'@./test.rb:22>
[:foo, :bar]
#<TracePoint:call `qux'@./test.rb:23>
[:foo, :bar, :baz]
#<TracePoint:call `bar'@./test.rb:21>
[:foo, :bar, :baz, :qux]
RECURSION DETECTED: method `qux` calls method `bar`.
Ruby的递归如何'sabotaged'禁用ruby方法进行递归的能力?
需要创建一个程序来教授 lambda 演算,但使用 Ruby。
来自 Crockford 的动机 JavaScript - https://www.youtube.com/watch?v=ya4UHuXNygM&feature=youtu.be&t=1h9m53s
您可以使用 TracePoint
API 来跟踪所有方法调用,并 returns 并构建堆栈以查看调用的方法是否已经在堆栈中。这样,您至少可以 检测 递归,然后您可以 raise
异常或 exit
程序。
类似于:
stack = []
TracePoint.trace(:call, :return) do |trace|
p trace, stack
method = trace.method_id
case trace.event
when :call
if stack.include?(method)
$stderr.puts "RECURSION DETECTED: method `#{stack.last}` calls method `#{method}`."
exit!
end
stack.push(method)
when :return
stack.pop
end
end
def foo; bar end
def bar; baz end
def baz; qux end
def qux; bar end
foo
请注意,我在其中插入了一个调试 p
rint,以便您可以观察它是如何工作的:
#<TracePoint:call `foo'@./test.rb:20>
[]
#<TracePoint:call `bar'@./test.rb:21>
[:foo]
#<TracePoint:call `baz'@./test.rb:22>
[:foo, :bar]
#<TracePoint:call `qux'@./test.rb:23>
[:foo, :bar, :baz]
#<TracePoint:call `bar'@./test.rb:21>
[:foo, :bar, :baz, :qux]
RECURSION DETECTED: method `qux` calls method `bar`.