Skip to content

Instantly share code, notes, and snippets.

@forforf
Created October 10, 2011 01:43
Show Gist options
  • Save forforf/1274459 to your computer and use it in GitHub Desktop.
Save forforf/1274459 to your computer and use it in GitHub Desktop.
NEO-Refactoring 2
module NeoMethods
#include NeoProxy
#ThinProxy objects must be used when the object doesn't support #define_singleton_method (i.e. symbols)
#SymbolMethods = {:sym_add => lambda{|x| result = (self.to_s + x.to_s).to_sym; replace_self(result)} }
module Symbol
Methods = {
:sym_add => lambda do |x|
#proxy = ThinProxy.new(self)
sum = self.to_s + x.to_s
sum = sum.to_sym
replace_self(sum)
end
}
end
module Num
Methods = {
:num_add => lambda do |x|
puts "num self: #{self.inspect}"
sum = self.to_f + x.to_f
replace_self(sum)
end
}
end
end
module DataOps
include NeoMethods
Def = {
:syms => Symbol::Methods,
:nums => Num::Methods
}
end
module NeoProxy
include DataOps
class ThinProxy < BasicObject
attr_accessor :obj
def initialize(obj)
@obj = obj
end
def define_method(method_name, callable=nil, &block)
block ||= callable
metaclass = class << self; self; end
metaclass.send(:define_method, method_name, block)
end
def replace_self(new_obj)
@obj = new_obj
end
def method_missing(method, *args, &block)
obj.send(method, *args, &block)
end
end
def set_neo_methods(key, val=nil)
neo_hsh = {}
puts "setting neo meth: #{key.inspect}: #{val.inspect}"
#proxy_key = ThinProxy.new(key)
proxy_val = ThinProxy.new(val)
#proxy_key.define_method(proxy_key.to_sym, lambda{proxy_val})
#proxy_key.define_method(:[]=, new_value, proxy_key.replace_self
neo_methods = Def[key] #method_name => lambda, etc
neo_methods.each do |method_name, block|
proxy_val.define_method(method_name, block)
end
#neo_hsh[proxy_key] = proxy_val
neo_hsh[key] = proxy_val
neo_hsh
end
end
class TkSymBase
include NeoProxy
class << self; attr_accessor :data_ops, end
self.data_ops = nil #to be set by base classes
def initialize(hsh_orig = {})
plain_hsh = hsh_orig.dup
proxy_hsh = {}
plain_hsh.each do |k,v|
#proxy_obj = ThinProxy.new(v)
#self.class.__send__(:define_method, "#{k}".to_sym, lambda {hsh[k]} )
#self.class.__send__(:define_method, "#{k}=".to_sym, lambda {|new_val| hsh[k] = proxy_obj} )
#obj_methods.each do |method_name, block|
# proxy_obj.define_singleton_method(method_name, block)
# #backwards compatibility to tinkit
# #also a way to avoid chaining send methods when calling the method dynamically
# tk_meth_name = "#{k}_#{method_name}".to_sym
# #define a method on self that calls the proxy_obj method just defined
# self.define_singleton_method(tk_meth_name, lambda{|x| proxy_obj.__send__(method_name, x)})
#end
#self.class.data_ops.each do |key, ops|
#end
neo_data = set_neo_methods(k,v)
proxy_hsh.merge!(neo_data)
p proxy_hsh.values.first.sym_add(:foo)
p proxy_hsh[k].sym_add(:bar)
end
proxy_hsh.each do |k, proxy_v|
self.class.__send__(:define_method, k.to_sym, lambda{proxy_hsh[k]})
puts "test"
p k
p self.__send__ k.to_sym
end
end
def add_data(hsh)
new_hsh = {}
hsh.each do |k,v|
neo_data = set_neo_methods(k,v)
new_hsh.merge!(neo_data)
end
new_hsh.each do |k, proxy_v|
self.class.__send__(:define_method, k.to_sym, lambda{new_hsh[k]})
end
end
end
module TkSymFactory
#include TkSyms
def self.make(data_ops_def)
#tkClass = TkSyms.const_set(className.to_sym, TkSymBase)
tkClass = Class.new(TkSymBase)
data_ops_def.each do |key, ops|
tkClass.data_ops = data_ops_def
#ops.instance_methods.each do |inst_meth|
end
tkClass
end
end
MyTkClass = TkSymFactory.make(DataOps::Def)
p MyTkClass
p MyTkClass.instance_methods
h = {:syms => :a}
x = MyTkClass.new(h)
p x
p x.syms
#p x.syms.instance_methods
p x.syms.sym_add(:b)
x.add_data(:nums => 1)
p x
p x.nums
p x.nums.num_add(4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment