Amb In Ruby

last modified: May 21, 2008

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


CategoryRuby


Loading...