0

我正在编写一个用于约束处理的 ruby​​ 模块。

(作为我的小经验,主要是关于使用给定域和搜索和修剪来实例化变量)

我的意图

的实例Constraint将使用一组变量名和一个块进行初始化。将评估该块以检查初始化是否满足约束。

用一个块喂食,它的类方法Constraint.subclass返回一个子类Constraint,比如说Subclass1

Subclass1中,有一个带有预定义块(馈入的块Constraint.subclass)的初始化程序和一个类方法Subclass1.invert。后者通过再次使用返回另一个子类Constraint,例如。Subclass2Constraint.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

资源

在 ruby​​1.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
4

0 回答 0