我正在编写一个用于约束处理的 ruby 模块。
(作为我的小经验,主要是关于使用给定域和搜索和修剪来实例化变量)
我的意图
的实例Constraint
将使用一组变量名和一个块进行初始化。将评估该块以检查初始化是否满足约束。
用一个块喂食,它的类方法Constraint.subclass
返回一个子类Constraint
,比如说Subclass1
在Subclass1
中,有一个带有预定义块(馈入的块Constraint.subclass
)的初始化程序和一个类方法Subclass1.invert
。后者通过再次使用返回另一个子类Constraint
,例如。Subclass2
Constraint.subclass
并且预定义的块Subclass2
应该是 in 的反转版本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
资源
在 ruby1.9 中列出如下。较少相关的方法被省略,完整版本可在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