Aleksi writes: > In [ruby-talk:01697] at > http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/~poffice/mail/rub > y-talk/1697 > gotoken writes > > Ruby doesn't have unbounded methods as first class data, > > which makes me wonder why - it's such a marvellous OO lang > with dedication for first-classness. > > Why we have bounded methods, like blocks, but not > semibounded, like instance > methods, nor unbounded, like classmethods? and answers to himself: Well, we *can* have objects for instance methods and class methods. The next snippet contains one routine which should not belong there, but I bundled it anyway. It's the Kernel#get_named. It takes the *rest argument container as argument and returns the last contained hash if any. So one can effectively use it with a definition and call like this def varying_number_of_arguments_and_named_parameter(*rest) named = get_named(rest) p rest named.each do |key, value| puts "#{key}=#{value}" end end varying_number_of_arguments_and_named_parameter( 'param1', 'param2, 'test' => 'with', 'named' => 'arguments' ) Should print: ['param1, 'param2'] test=with named=arguments But now to the point, here's the code that enables one to have a reference to instance's method and call it like this: instanceMethod = InstanceMethod.new(Test.new, :method ) instanceMethod.call('argument') class Method # the calling interface def call raise "not implemented in abstract base class!" end end class Block #< Method def initialize( block=nil, &bk ) @block = block if block @block = bk if bk raise "no block defined" unless defined? @block end def call(*args) # associated block should get @block.call(*args) # passed, but apparently won't end end class InstanceMethod #< Method def initialize( instance, method ) @instance = instance @method = method end def call(*args, &blk) @instance.send(@method, *args, &blk) end end # InstanceMethod works for ClassMethods too # The instance passed to constructor should be # object ClassName (which is instance of class Class) class ClassMethod < InstanceMethod end module Kernel # three helper methods, for convenience def inst_proc( instance, method ) InstanceMethod.new instance, method end def class_proc( klass, method ) ClassMethod.new klass, method end def block_proc( block=nil, &bk ) return Block.new(block) if block return Block.new(bk) if bk end def get_named(rest) # can make errors (rest.size-1).downto(0) do |i| return rest.delete_at(i) if rest[i].kind_of? Hash end return Hash.new end end ################################ ################################ And here's the test case (and example): require 'Method' class Test def initialize(test) @test = test end def Test.test_class_method( arg, *rest, &bl) named = get_named(rest) puts "Class Method" puts arg p rest named.each do |key, value| puts "#{key}=#{value}" end bl.call end def test_instance_method( arg, opt="optional", &bl) puts "Instance method" puts @test puts arg puts opt bl.call end def test_block_method return proc { |arg, *rest| puts "Block_method" puts @test puts arg p rest # yield if iterator? } end end #classMethod = ClassMethod.new(Test, :test_class_method ) classMethod = class_proc(Test, :test_class_method ) classMethod.call('argument', 'rest', 'test', 'test' => 'with', 'named' => 'arguments' ) do puts "class method block test" end puts test = Test.new("instance_data") instanceMethod = InstanceMethod.new(test, :test_instance_method ) instanceMethod.call('argument') do puts "instance method block test" end puts inst_proc(test, :test_instance_method).call('argument', 'optional set') do puts "instance method block test" end puts test = Test.new("bound instance data") procInstance = test.test_block_method block = block_proc( procInstance ) block.call('argument', 'rest', 'test') do puts "'block associated to block'-test would be here" puts "but it seems there's no such thing" end puts puts "Block_method: plain associated block" block = Block.new do puts "here I am" end block.call - Aleksi