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<
-----------------------------------------