Created
March 28, 2011 11:18
-
-
Save lfborjas/890302 to your computer and use it in GitHub Desktop.
Examples of continuations
This file contains hidden or 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
class Array | |
def one_at_a_time | |
control_state = lambda do |ret| | |
each do |elem| | |
callcc do |resume| | |
control_state = lambda do |r| | |
resume.call r | |
end | |
ret.call elem | |
end | |
end | |
ret.call :you_fell | |
end | |
lambda { callcc {|k| control_state.call(k)} } | |
end | |
def rest | |
self.slice 1..-1 | |
end | |
def tree_generator | |
caller = nil | |
generate_leaves = lambda do | |
loop = lambda do |tree| | |
if tree.is_a?(Array) and tree.empty? | |
nil | |
elsif tree.is_a? Array | |
loop.call tree.first | |
loop.call tree.rest | |
else | |
callcc do |rest_of_tree| | |
generate_leaves = lambda{rest_of_tree.call(:resume)} | |
caller.call tree | |
end | |
end | |
end | |
loop.call(self) | |
end | |
lambda do | |
callcc do |k| | |
caller = k | |
generate_leaves.call | |
end | |
end | |
end | |
def same_fringe?(o) | |
gen1 = self.tree_generator | |
gen2 = o.tree_generator | |
loop do | |
leaf1 = gen1.call | |
leaf2 = gen2.call | |
if leaf1 == leaf2 | |
if leaf1.nil? | |
return true | |
end | |
else | |
return false | |
end | |
end | |
end | |
#was trying to do this: | |
#http://www.ccs.neu.edu/home/dorai/t-y-scheme/t-y-scheme-Z-H-1.html#node_toc_node_sec_13.4 | |
#but just cant find a way to implement the resume method well... I tried instance methods, | |
#and class methods, but I can't find a way to access the current coroutine and the other one | |
#in the blocks passed to new!!!! | |
def eqfringe?(o) | |
#LOOK MA! A letrec simulation!!! | |
#used lambda to mimic lazy evaluation and can now define leafer1 and leafer2 in terms of something | |
#that doesn't exist yet! | |
matcher = nil | |
letrec = { | |
:leafer1 => lambda{make_gen(self, matcher)}, | |
:leafer2 => lambda{make_gen(o, matcher)} | |
} | |
matcher = lambda{make_matcher(letrec[:leafer1].call, letrec[:leafer2].call)} | |
matcher.call.invoke | |
end | |
private | |
def make_matcher(tree_cor1, tree_cor2) | |
Coroutine.new do | |
rval = false | |
loop do | |
leaf1 = Coroutine.resume c, tree_cor1 | |
leaf2 = Coroutine.resume c, tree_cor2 | |
if leaf1 == leaf2 | |
if leaf1.nil? then rval = true; break end | |
else | |
break | |
end | |
end | |
rval | |
end | |
end | |
def make_gen(t, matcher) | |
Coroutine.new do | |
loop = lambda do |tree| | |
if tree.is_a?(Array) and tree.empty? | |
nil | |
elsif tree.is_a? Array | |
loop.call tree.first | |
loop.call tree.rest | |
else | |
Coroutine.resume self, matcher, tree | |
end | |
end | |
loop.call(t) | |
end | |
end | |
end | |
class Coroutine | |
attr_accessor :resume, :control_state | |
def initialize(&body) | |
@control_state = proc &body | |
end | |
def invoke(v=nil) | |
@control_state.call v | |
end | |
def self.resume(s, c, v=nil) | |
callcc do |k| | |
s.control_state = k | |
c.invoke v | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment