我正在编写一个用于约束处理的ruby模块。
(正如我的经验,主要是关于使用给定域和搜索和修剪来实现变量的实现)
Constraint
的实例将使用一组变量名和一个块进行初始化。将评估该块以检查初始化是否满足约束。
使用一个块,它的类方法Constraint.subclass
返回Constraint
的子类,比如Subclass1
在Subclass1
中,有一个带有预定义块的初始化器(一个被馈送到Constraint.subclass
)和一个类方法Subclass1.invert
。后者再次使用Constraint
返回Subclass2
的另一个子类,比如Constraint.subclass
。
Subclass2
中的预定义块应该是Subclass1
代码或多或少按我的意图行事。 Constraint.subclass
有效,但似乎Subclass.invert
仅在预定义块具有确定性时才起作用。否则stack level too deep
将会出现。
#worked
EQ = Constraint.subclass {|a,b| a == b }
NE = EQ.invert
ALL_DISTINCT = Constraint.subclass {|*args| args.uniq.size == args.size}
#raised stackoverflow
HAVE_DUPLICATE = ALL_DISTINCT.invert
。省略了较少的核心方法,https://gist.github.com/2882291
提供完整版本module Solver
class Constraint # class method for a subclass
def self.subclass &block
Class.new(self) do
@@block = block
def initialize *args
super *args, &@@block
end
def self.invert # class method for a cousin class of current subclass
p "#{self}.invert"
new_block = proc {|*args| not @@block.call(*args)}
self.superclass.subclass &new_block
end
end
end
def initialize *vars, &block
# block will be substituted with variable in vars
raise ArgumentError "array of variable names is required"unless vars.is_a? Array
raise ArgumentError "block is expected" unless block_given?
@vars = vars.freeze
@proc = block.freeze
end
# less related methods
end
# predefined constraint schema
EQ = Constraint.subclass {|a,b| a == b }
NE = EQ.invert
GT = Constraint.subclass {|a,b| a > b }
NGT = GT.invert
LT = Constraint.subclass {|a,b| a < b }
NLT = LT.invert
ALL_DISTINCT = Constraint.subclass {|*args| args.uniq.size == args.size}
#HAVE_DUPLICATE = ALL_DISTINCT.invert
end