def generator_for(handle, args = {}, &block)
      if handle.is_a?(Hash)
        raise ArgumentError, "only specify one attr => value pair at a time" unless handle.keys.length == 1
        gen_data = handle
        handle = gen_data.keys.first
        args = gen_data[handle]
      end
      
      raise ArgumentError, "an attribute name must be specified" unless handle = handle.to_sym
      
      unless args.is_a?(Hash)
        unless block
          retval = args
          block = lambda { retval }  # lambda { args } results in returning the empty hash that args gets changed to
        end
        args = {}  # args is assumed to be a hash for the rest of the method
      end
      
      if args[:start]
        block ||= lambda { |prev|  prev.succ }
      end
      
      if args[:method]
        h = { :method => args[:method].to_sym }
        h[:start] = args[:start] if args[:start]
        record_generator_for(handle, h)
      elsif args[:class]
        raise ArgumentError, "generator class [#{args[:class].name}] does not have a :next method" unless args[:class].respond_to?(:next)
        record_generator_for(handle, :class => args[:class])
      elsif block
        raise ArgumentError, "generator block must take an optional single argument" unless (-1..1).include?(block.arity)  # NOTE: lambda {} has an arity of -1, while lambda {||} has an arity of 0
        h = { :block => block }
        h[:start] = args[:start] if args[:start]
        record_generator_for(handle, h)
      else
        raise ArgumentError, "a block, :class generator, :method generator, or value must be specified to generator_for"
      end
    end
def generator_for(handle, args = {}, &block)
      if handle.is_a?(Hash)
        raise ArgumentError, "only specify one attr => value pair at a time" unless handle.keys.length == 1
        gen_data = handle
        handle = gen_data.keys.first
        args = gen_data[handle]
      end
      
      raise ArgumentError, "an attribute name must be specified" unless handle = handle.to_sym
      
      unless args.is_a?(Hash)
        unless block
          retval = args
          block = lambda { retval }  # lambda { args } results in returning the empty hash that args gets changed to
        end
        args = {}  # args is assumed to be a hash for the rest of the method
      end
      
      if args[:start]
        block ||= lambda { |prev|  prev.succ }
      end
      
      if args[:method]
        h = { :method => args[:method].to_sym }
        h[:start] = args[:start] if args[:start]
        record_generator_for(handle, h)
      elsif args[:class]
        raise ArgumentError, "generator class [#{args[:class].name}] does not have a :next method" unless args[:class].respond_to?(:next)
        record_generator_for(handle, :class => args[:class])
      elsif block
        raise ArgumentError, "generator block must take an optional single argument" unless (-1..1).include?(block.arity)  # NOTE: lambda {} has an arity of -1, while lambda {||} has an arity of 0
        h = { :block => block }
        h[:start] = args[:start] if args[:start]
        record_generator_for(handle, h)
      else
        raise ArgumentError, "a block, :class generator, :method generator, or value must be specified to generator_for"
      end
    end
register a generator for an attribute of this class
 generator_for :foo do |prev| ... end
 generator_for :foo do ... end
 generator_for :foo, value
 generator_for :foo => value
 generator_for :foo, :class => GeneratorClass
 generator_for :foo, :method => :method_name