module Kernel
def at(a)
cc = a.shift.new(*a)
self.class_eval {
org = method(:method_added)
send :define_singleton_method,:method_added, &lambda{|sym, *args|
return org.call(sym, *args) if (sym==:method_added)
send(:define_singleton_method,:method_added, &org)
x = instance_method(sym)
send(:define_method, sym, &cc.call(sym, x))
}
}
end
class Author
def initialize(name)
@name = name
end
def call(sym, block)
name = @name
lambda {|*args|
puts "Author #{name}\nFunction #{sym}"
block.bind(instance_eval{self}).call(*args)
}
end
end
class Rev
def initialize(rev)
@rev = rev
end
def call(sym, block)
rev = @rev
lambda {|*args|
puts "Revision: #{rev}"
block.call(*args)
}
end
end
at [Rev, 5]
def print_hello
puts "Hello world"
end
at [Author, "pochy"]
def ok
puts "ok"
end
print_hello
ok
ok
end
class Check
def initialize(*args)
@x = *args
end
def call(sym, block)
x = @x
lambda{|*args|
raise "Wrong number of arguments (#{args.length} of #{x.length}" if args.length != x.length
x.each_index{|i|
raise "Type error #{args[i].class} for #{x[i]}" unless args[i].class==x[i]
}
block.bind(instance_eval{self}).call(*args)
}
end
end
class A
at [Check, Fixnum, Fixnum]
def add(a,b)
a+b
end
end
puts A.new.add(3,4,5)module Kernel
def at(a)
cc = a.shift.new(*a