On Wed, Aug 27, 2008 at 11:08 AM, Toby Clemson <tobyclemson / gmail.com> wrote:
I am currently working on a new release of Labardor, but there still
is sooo much to do, however, you might be interested in the following
code of Labrador.
I am however aware that this implies a rethink of your strategy,
however one of my goals is to explore different behavior based OO
approaches than inheritance and mixins, in case you find that a useful
paradigm shift.
And I appologize for the long post but Labrador just is in no shape
for a new release to Rubyforge.

HTH
Robert
Skip the rest if you are not particularily interested in different OO
approaches.
----------------------------- 8< ------------------------
#--
# vim: sts=2 sw=2 tw=0 expandtab nu:
#*
#* Labrador, The Lazy Programmer's Best Friend.
#*
#* Distributed under the terms of the BSD License.
#* Copyright (c) 2007 Robert Dober
#* All rights reserved.
#*
#* Redistribution and use in source and binary forms, with or without
#* modification, are permitted provided that the following conditions are met:
#*     * Redistributions of source code must retain the above copyright
#*       notice, this list of conditions and the following disclaimer.
#*     * Redistributions in binary form must reproduce the above copyright
#*       notice, this list of conditions and the following disclaimer in the
#*       documentation and/or other materials provided with the distribution.
#*     * Neither the name of the Labrador packahe nor the
#*       names of its contributors may be used to endorse or promote products
#*       derived from this software without specific prior written permission.
#*
#* THIS SOFTWARE IS PROVIDED BY Robert Dober ``AS IS'' AND ANY
#* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#* DISCLAIMED. IN NO EVENT SHALL Robert Dober BE LIABLE FOR ANY
#* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#++

class Array

  def ivar_names_to_strings
    map { |ele| ele.to_s.sub("@","") }
  end

  def ivar_names_to_symbols
    map { |ele| ele.to_s.sub("@","").to_sym }
  end
  def names_to_ivar_strings
    map { |ele| "@#{ele.to_s.sub("@","")}" }
  end

  def names_to_ivar_symbols
    map { |ele| "@#{ele.to_s.sub("@","")}".to_sym }
  end

end # class Array


class Object
  def get_ivars *ivars
    ivars = instance_variables if ivars.empty?
    ivars.ivar_names_to_symbols.
      inject( {} ) { |h, ivar|
        h.update ivar => instance_variable_get( "@#{ivar}" )
      }
  end

  def pop_ivars
    set_ivars! @__ivar_stack__.pop
  end

  def push_ivars hash
    ( @__ivar_stack__ ||= [] ).
      push(
           get_ivars( *hash.keys )
          )
    set_ivars! hash
  end

  def set_ivars hash
    hash.keys.each do
      | ivar |
      ivar_name = "@#{ivar}".sub( /^@@/, "@" )
      instance_variable_set ivar_name, hash[ ivar ] unless
        instance_variables.include? ivar_name
    end
  end

  def set_ivars! hash
    hash.keys.each do
      | ivar |
      ivar_name = "@#{ivar}".sub( /^@@/, "@" )
      instance_variable_set ivar_name, hash[ ivar ]
    end
  end

  def set_only_ivars hash, *keys
    set_ivars hash.keys.inject( {} ){ |h, k|
      keys.include?( k ) ? h.update( k => hash[k] ) : h
    }
  end # def set_only_ivars hash, *keys

  def set_only_ivars! hash, *keys
    set_ivars! hash.keys.inject( {} ){ |h, k|
      keys.include?( k ) ? h.update( k => hash[k] ) : h
    }
  end # def set_only_ivars hash, *keys
end # class Object

class Behavior
  attr_reader :block
  def initialize &blk
    @block = blk
  end
end

module Kernel
  def Behavior &blk
    Behavior::new &blk
  end
end

class Module
  def empty?; instance_methods.empty? end
  def empty!; instance_methods.each do |im| remove_method im end end
end

module Pushable
  CannotPopException = Class::new RuntimeError
  ArgumentError      = Class::new ::ArgumentError

  def pop_behavior
    @__bsp__ -= 1
    raise CannotPopException, "empty entity #{self}" if @__bsp__ < 0
    @__behavior_stack__[@__bsp__].empty!
  end

  def push_behavior *behaviors, &blk
    @__behavior_stack__ ||= []
    @__bsp__ ||= 0
    raise ArgumentError,
      "push_behavior takes at least one behavior or block" if
        behaviors.empty? and blk.nil?

    behaviors.each do |behavior|
      _push_behavior  behavior
    end

    _push_behavior blk if blk
    self
  end

  private

  def _push_behavior behavior
    m = @__behavior_stack__[@__bsp__]
    @__behavior_stack__ << ( m = Module::new ) unless m
    include m rescue extend m # this is autoprotected against double
inclusion; so finally turns out it is a feature ;)
    m.empty!
    m.module_eval &(behavior.block rescue behavior)
    @__bsp__ += 1
  end
end # module Pushable

class << Pushable
  def new *args, &blk
    c = Class::new( *args, &blk )
    c.extend self
    c
  end
end # class << Pushable

class << PushableModule = Module::new
  def new *args, &blk
    m = Module::new( *args, &blk )
    m.extend Pushable
    m
  end
end
------------------------------------ 8<
-----------------------------------------