Created
October 26, 2011 08:38
-
-
Save headius/1315794 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
RESET_STACK = [] | |
SHIFT_MAP = {} | |
def reset(&block) | |
RESET_STACK.push block | |
block.call() | |
ensure | |
RESET_STACK.pop | |
end | |
def shift(&block) | |
if SHIFT_MAP.key? block.source_location | |
ary = SHIFT_MAP[block.source_location] | |
value = ary.pop | |
SHIFT_MAP.delete(block.source_location) if ary.empty? | |
value | |
else | |
shift_proc = proc do |arg| | |
SHIFT_MAP[block.source_location] ||= [] | |
SHIFT_MAP[block.source_location].push arg | |
RESET_STACK[-1].call | |
end | |
block.call(shift_proc) | |
end | |
end | |
p reset { 2 * 2 } # 4 | |
p reset { 2 * shift {|k| 2 } } # 4 | |
p reset { 2 * shift {|k| k[2] } } # 8 | |
p reset { 2 * shift {|k| k[k[2]] } } # 16 | |
p reset { 2 * shift {|k| k[shift {|j| j[3]}] } } # 24 | |
p reset { 2 * shift {|k| k[3] + k[4]} } # 28 |
I'm interested in understanding more about shift-reset and was looking for more interesting examples where it would be useful and came across Christian's article.
Then I was trying to work out how the two implementations differed and why his example didn't work with your implementation. Stepping through the code in the different implementations was a bit of a mind-bender. Haven't used continuations in Ruby before.
Does the way you've implemented shift-reset prevent creating some kind of lazy forkable iterator similar to what Christian made with each_to_stream(collection)
?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@stephenb: Duh, thanks for the correction.
Yeah, of course this impl only works downstream from reset; you can't actually save off the continuation and call it from outside reset. That would only be possible with a library or JVM support for real continuations/coroutines.
My version obviously also deepens the stack for the nested continuation invokes, where a Lisp or Scheme VM would probably TCO some of those away.