Check out the Pastebin Gadgets Shop. We have thousands of fun, geeky & affordable gadgets on sale :-)Want more features on Pastebin? Sign Up, it's FREE!

# Untitled

By: a guest on Feb 27th, 2012  |  syntax: None  |  size: 1.32 KB  |  views: 21  |  expires: Never
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
1. # I got this idea from http://mihai.bazon.net/blog/redis-client-library-javascript-node
2. # The technique relies on the fact that raising an exception clears the call stack.
3. # The context is passed along with a block attached to an exception.
4. # I thought it was brilliant js hackery so I decided to try my hand at it in ruby.
5. # I've also included some other stack-dependent implementations.
6.
7. # straight recursion, not quite a tail-call
8. # I can't go above 8.1k without stack error
9. def rsum(num)
10.   if num == 0
11.     0
12.   else
13.     num + rsum(num - 1)
14.   end
15. end
16.
17. # tail-call block based recursion
18. # I can't go above 7.6k without stack error
19. def crsum(num, total = 0, &block)
20.   if num == 0
21.     yield total
22.   else
23.     crsum(num - 1, num + total, &block)
24.   end
25. end
26.
27. # Using blocks and exceptions to clear call stack
28. class Beer < RuntimeError
29.   attr_accessor :block
30.   def initialize(&block)
31.     @block = block
32.   end
33. end
34.
35. def cheers!(&block)
36.   raise Beer.new(&block)
37. end
38.
39. def cc(&block)
40.   loop do
41.     begin
42.       block.call
43.       break
44.     rescue Beer => beer
45.       block = beer.block
46.     end
47.   end
48. end
49.
50. def sum(num, total = 0, &block)
51.   if num == 0
52.     yield total
53.   else
54.     cheers! { sum(num - 1, num + total, &block) }
55.   end
56. end
57.
58. cc { sum(100) {|t| puts t} }
59.
60. # Run this block in irb.
61. # I got up to 100k and it still works!
62. # cc { sum(1000) {|total| puts total} }
clone this paste RAW Paste Data
Top