开发者

Exception clears the stack trace of what?

I am reading this blog and came across following code

RunAgain = Class.new(Exception)
def fib(i, n = 1, result = 0)
  if i == -1
    result
  else
    raise RunAgain
  end
rescue RunAgain
  i, n, result = i - 1, n + result, n
  r开发者_如何学编程etry
end

It seems like for above code to work, once exception is raised then ruby must be clearing the whole stack trace and replacing that with the stack of Exception.

Is my understanding right?


The way this code works actually has nothing to do with the stacktrace. There are two entries on the stack the entire time, fib and the caller of fib. The raise of the exception is sort of a red herring to your question--it doesn't serve any useful purpose in this example other than as a demonstration of the behavior of retry.

Ruby's retry is similar to other control keywords like next and break, and redo. The redo keyword means to retry the current loop or block from the top. The retry keyword works inside a rescue to retry the current block that threw the exception.

So what happens here is some initial values are set for i, n, and result, a base case is checked (i == -1), and if not satisfied, we update the values and retry from the top. Notice that since these values are method parameters and not local variables, they are not reinitialized.

Careful, since Fibonacci is a very common example (and a very poor one) of recursion, not to mistake this for a recursive algorithm. The RunAgain raise and rescue functions like a loop, without re-calling the function or modifying the callstack.

Your example code is equivalent to

def fib(i)
  n, result = 1, 0
  (i+1).times { n, result = n + result, n }
  result
end

Note in both cases, i is just a counter and nothing more. We run the code i+1 times. Note also the typical need for a temporary variable to swap values is replaced by ruby's multiple assignment construct.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜