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.