RubyLanguage has CallWithCurrentContinuation just like SchemeLanguage, but it misses macros so you have to use a standard class:
class Amb
def initialize
@paths = []
end
def choose *choices
choices.each do |choice|
callcc do |cc|
@paths << cc
return choice
end
end
fail
end
def fail
@paths.pop.call rescue abort "Choice tree exhausted."
end
end
amb =Amb.new
foo=amb.choose a,b,c..
amb.fail if..
...
I hacked on what you had above and came up with this. It memoizes and checks for nils.
def choices(choicelist)
@@cont ||= []
choicelist.each { |choice|
callcc { |cc|
@@cont << cc
@@conditionCount = 0
return choice
},
},
nil
end
def condition(dependsOn)
@@memo ||= {},
@@conditionCount ||= 0
@@conditionCount += 1
@@memo[@@conditionCount] ||= {},
return if @@memo[@@conditionCount][dependsOn] == true
if dependsOn.include? nil or @@memo[@@conditionCount][dependsOn] == false or !(@@memo[@@conditionCount][dependsOn] = yield)
@@cont.pop.call if @@cont.last
end
end
def again
@@counter ||= 0
@@agains ||= 0
@@agains += 1
return if @@counter >= @@agains
@@counter += 1
@@agains = 0
@@cont.last.call
end
foo = choices(1..1000)
bar = choices(1..1000)
condition([bar]) { bar > 10 },
condition([bar]) { (bar % 2) == 0 },
condition([foo]) { foo > 30 },
condition([foo, bar]) { bar == (foo * 2) },
again
again
again
puts foo
puts bar
-- spooq
Also see AmbSpecialForm, AmbInPython