From: Trans Date: 2005-08-19T19:26:16+09:00 Subject: finding one's self in the strangest places Hello, Thought this was interesting for a numbner of reasons, not the least of which is that I am suprised it even works. What it is is whay to do dynamic module mixins, i.e. including modules with macro-like changes in behavior. Note that the first three lines simply add those well known methods to the Binding class. require 'nano/binding/self' require 'nano/binding/%5B%5D%3D' # []= require 'nano/binding/local_variables' class Module def module_options @module_options ||= {} end alias_method :include_without_options, :include def include(*args) base = self options = args.last.is_a?(Hash) ? args.pop : {} mods = args.collect do |mod| mod.append_dynamic_features( self, options ) mod end include_without_options(*mods) end # Note: Is this the best name for this callback? def append_dynamic_features( base, options ) mod = self base.module_options[mod] = options end # vars is just a dummy slot, does nothing def dynamic_mixin( space, *vars ) mod = space.self space.local_variables.each { |v| default = space[v.to_sym] space[v.to_sym] = lambda { |base| base.class.module_options[mod][v.to_sym] || default } } end end # try it if $0 == __FILE__ module MyDynamix dynamic_mixin( binding, name='Tom' ) # name is local var define_method( :hello ) { puts "Hello from #{name[self]}" } define_method( :goodbye ) { puts "Goodbye from #{name[self]}" } end class MyClass include MyDynamix, :name => 'George' end m = MyClass.new m.hello #=> Hello from George m.goodbye #=> Hello from George class MyClass2 include MyDynamix end m = MyClass2.new m.hello #=> Hello from Tom m.goodbye #=> Hello from Tom end What amazes me about this is that 'name' in 'name[self]' is a local variable assigned to a lambda, yet 'self' is not and rather belongs to the initialized instance of the class. How is that possible? How is execution of the lambda deferred til later? I think this is a facinating example of Ruby's "juggling" abilities. Also, it would be nice to be able to take this one step further, if it were possible NOT to have to explictly pass 'binding' via #dyanmic_mixin or pass 'self' via the local var lambda, then it would be perfect. T.