class NEAT::NeatOb

Basis of all NEAT objects. NeatOb has support for NEAT attributes with special support for hooks and queues.

Attributes

controller[R]

Who's your daddy?

name[R]

Designation of this particular object instance

Public Class Methods

attr_neat(sym, default: nil, cloneable: nil, hooks: false, queue: false) click to toggle source

Defaultable attributes of neat attributes.

If hooks: true is given, two hook functions are created:

<sym>_add() -- add a hook
<sym>_set() -- set a hook, overwriting all other hooks set or added.
<sym>_clear -- clear all hooks
<sym>_none? -- return true if no hooks are defined.
<sym>_one? -- return true if exactly hook is defined.
<sym>_hook() -- for passing unnamed parameters to a singular hook.
<sym>_np_hook() -- for passing unnamed parameters to a singular hook.
<sym>_hook_itself() -- for getting the proc reference to the hook.
<sym>_hooks() -- for passing unnamed parameters.
<sym>_np_hooks() -- for passing a named parameter list.

For *_hook(), the function returns the single result. For *_hooks(), the hook function return an array of results from all the actual registered hooks called.

# File lib/rubyneat/rubyneat.rb, line 153
def attr_neat(sym,
              default: nil,
              cloneable: nil,
              hooks: false,
              queue: false)
  svar = "@#{sym}"

  # Guess what clonable should be.
  # This is meant to cover "90%" of the cases.
  cloneable = case
                when default.nil?
                  false
                when default.kind_of?(Numeric)
                  false
                else
                  true
              end if cloneable.nil?

  # Sanity checks
  raise NeatException("Both hooks and queue cannot both be set for #{sym}.") if hooks and queue
  raise NeatException("Defaults cannot be defined for hooks and queues for #{sym}.") if (hooks or queue) and not default.nil?

  if hooks
    default = []
    cloneable = true
    hook_setup sym
  end

  if queue
    default = QDing.new
    cloneable = true
    queue_setup sym
  end

  define_method("#{sym}=") do |v|
    instance_variable_set(svar, v)
  end unless hooks or queue

  # TODO: Enhance this getter method for performance.
  define_method(sym) do
    instance_variable_set(svar,
                          instance_variable_get(svar) ||
                              ((cloneable) ? default.clone
                                           : default))
  end
end
log() click to toggle source
# File lib/rubyneat/rubyneat.rb, line 109
def self.log ; $log; end
new(controller = nil, name = nil) click to toggle source

Initializer for all NEAT objects. Requires that the controller object is specified for all classes with the exception of the Controller itself or the Controller's NeatSettings.

# File lib/rubyneat/rubyneat.rb, line 115
def initialize(controller = nil, name = nil)
  @name = unless name.nil?
            name.to_sym
          else
            NEAT::random_name_generator
          end
  unless controller.nil?
    @controller = controller
  else
    raise NeatException.new "Controller Needed!" unless self.is_a?(Controller) or self.is_a?(Controller::NeatSettings)
    @controller = self unless self.is_a? Controller::NeatSettings
  end
end

Private Class Methods

hook_setup(sym) click to toggle source
# File lib/rubyneat/rubyneat.rb, line 201
def hook_setup(sym)
  define_method("#{sym}_add") do |&hook|
    send(sym) << hook
  end

  define_method("#{sym}_set") do |&hook|
    send(sym).clear
    send(sym) << hook
  end

  define_method("#{sym}_clear") do
    send(sym).clear
  end

  define_method("#{sym}_none?") do
    send(sym).empty?
  end

  define_method("#{sym}_one?") do
    send(sym).size == 1
  end

  # hooks with named parameters
  define_method("#{sym}_np_hooks") do |**hparams|
    send(sym).map{|funct| funct.(**hparams)}
  end

  # hooks with traditional parameters
  define_method("#{sym}_hooks") do |*params|
    send(sym).map{|funct| funct.(*params)}
  end

  # TODO: DRY up the following functions, which does size checking in exacly the same way.
  # Single hook with named parameters
  define_method("#{sym}_np_hook") do |**hparams|
    sz = send(sym).size
    raise NeatException.new("#{sym}_np_hook must have exactly one hook (#{sz})") unless sz == 1
    send(sym).map{|funct| funct.(**hparams)}.first
  end

  # Single hook with traditional parameters
  define_method("#{sym}_hook") do |*params|
    sz = send(sym).size
    raise NeatException.new("#{sym}_hook must have exactly one hook (#{sz})") unless sz == 1
    send(sym).map{|funct| funct.(*params)}.first
  end

  # Get the singular hook function
  define_method("#{sym}_hook_itself") do
    sz = send(sym).size
    raise NeatException.new("#{sym}_hook_itself must have exactly one hook (#{sz})") unless sz == 1
    send(sym).first
  end
end
queue_setup(sym) click to toggle source
# File lib/rubyneat/rubyneat.rb, line 256
def queue_setup(sym)
  # Add boilerplate code for queues here.
end

Public Instance Methods

log() click to toggle source
# File lib/rubyneat/rubyneat.rb, line 108
def log ; $log ; end
to_s() click to toggle source
# File lib/rubyneat/rubyneat.rb, line 129
def to_s
  "%s<%s>" % [self.class, self.name]
end