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