[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Dynamically adding methods to a Ruby class

John Lam

12/15/2005 4:08:00 AM

I just finished writing the first spike for my Ruby CLR bridge tonight, and
I'm wondering if there might be a better (or more efficient) way to add
instance methods to a class object than this:

class Module
def const_missing(symbol)
obj = Class.new
obj.class_eval %{
def initialize
...
end

def method_missing(name, *params)
...
end
}
const_set(symbol, obj)
end
end

Thanks,
-John
http://www.iu...

PS If you're wondering what the code in the ... blocks do, read my write-up
of this code at: http://www.iu.../articles/2005/12/14/hello-rubyclr
6 Answers

Eero Saynatkari

12/15/2005 4:43:00 AM

0

John Lam wrote:
> I just finished writing the first spike for my Ruby CLR bridge tonight,
> and
> I'm wondering if there might be a better (or more efficient) way to add
> instance methods to a class object than this:
>
> class Module
> def const_missing(symbol)
> obj = Class.new
> obj.class_eval %{
> def initialize
> ...
> end
>
> def method_missing(name, *params)
> ...
> end
> }
> const_set(symbol, obj)
> end
> end

Not really, except for using define_method (which has
some limitations that would probably make it unsuitable
for a #method_missing implementation). The 'Class methods'
thread had pretty much this exact implementation..

Perhaps some sort of a prototype-based approach?

> Thanks,
> -John
> http://www.iu...
>
> PS If you're wondering what the code in the ... blocks do, read my
> write-up
> of this code at:
> http://www.iu.../articles/2005/12/14/hello-rubyclr


E

--
Posted via http://www.ruby-....


Brian Takita

12/15/2005 7:52:00 AM

0

Hello John,

This isn't quite as cool as a prototype, but here is another possible type
of solution:

class Dynamic
attr_reader :dynamic_methods

def initialize
@dynamic_methods = Hash.new
end

alias alias_method_missing method_missing

def method_missing(name, *args)
unless @dynamic_methods.include?(name)
alias_method_missing(name, *args)
return
end

@dynamic_methods[name].call(*args)
end
end

d = Dynamic.new

# You can also use Proc.new instead of lambda
d.dynamic_methods[:test] = lambda do |*args|
puts 'test ' + args.to_s
end

d.test(1, 2)
# test 12

Of course you could add the method that you describe in your link:

d.dynamic_methods[:Count] = lambda do |*args|
create_ruby_instance_method(self.class, 'Count') do
include 'System.Collections'
ldarg_2
call 'static Marshal::ToClrObject(VALUE)'
call 'ArrayList::get_Count()'
call 'static Marshal::ToRubyNumber(Int32)'
ret
end
self.Count
end

--
Brian Takita
http://freeo...

On 12/14/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
>
> John Lam wrote:
> > I just finished writing the first spike for my Ruby CLR bridge tonight,
> > and
> > I'm wondering if there might be a better (or more efficient) way to add
> > instance methods to a class object than this:
> >
> > class Module
> > def const_missing(symbol)
> > obj = Class.new
> > obj.class_eval %{
> > def initialize
> > ...
> > end
> >
> > def method_missing(name, *params)
> > ...
> > end
> > }
> > const_set(symbol, obj)
> > end
> > end
>
> Not really, except for using define_method (which has
> some limitations that would probably make it unsuitable
> for a #method_missing implementation). The 'Class methods'
> thread had pretty much this exact implementation..
>
> Perhaps some sort of a prototype-based approach?
>
> > Thanks,
> > -John
> > http://www.iu...
> >
> > PS If you're wondering what the code in the ... blocks do, read my
> > write-up
> > of this code at:
> > http://www.iu.../articles/2005/12/14/hello-rubyclr
>
>
> E
>
> --
> Posted via http://www.ruby-....
>
>

Brian Takita

12/15/2005 8:18:00 AM

0

Oops...
In the :Count method I defined, self isn't the same as in the method you
defined.

caller[1] probably would be the object you are looking for as long as that
method gets called through :method_missing in this case. :self could be used
if the dynamic method is defined in the class though.

d.dynamic_methods[:Count] = lambda do |*args|
create_ruby_instance_method(caller[1].class, 'Count') do
include 'System.Collections'
ldarg_2
call 'static Marshal::ToClrObject(VALUE)'
call 'ArrayList::get_Count()'
call 'static Marshal::ToRubyNumber(Int32)'
ret
end
caller[1].Count
end

--
Brian Takita
http://freeo...

On 12/14/05, Brian Takita <brian.takita@gmail.com> wrote:
>
> Hello John,
>
> This isn't quite as cool as a prototype, but here is another possible type
> of solution:
>
> class Dynamic
> attr_reader :dynamic_methods
>
> def initialize
> @dynamic_methods = Hash.new
> end
>
> alias alias_method_missing method_missing
>
> def method_missing(name, *args)
> unless @dynamic_methods.include?(name)
> alias_method_missing(name, *args)
> return
> end
>
> @dynamic_methods[name].call(*args)
> end
> end
>
> d = Dynamic.new
>
> # You can also use Proc.new instead of lambda
> d.dynamic_methods[:test] = lambda do |*args|
> puts 'test ' + args.to_s
> end
>
> d.test(1, 2)
> # test 12
>
> Of course you could add the method that you describe in your link:
>
> d.dynamic_methods[:Count] = lambda do |*args|
> create_ruby_instance_method( self.class, 'Count') do
> include 'System.Collections'
> ldarg_2
> call 'static Marshal::ToClrObject(VALUE)'
> call 'ArrayList::get_Count()'
> call 'static Marshal::ToRubyNumber(Int32)'
> ret
> end
> self.Count
> end
>
> --
> Brian Takita
> http://freeo...
>
> On 12/14/05, Eero Saynatkari <ruby-forum-reg@mailinator.com> wrote:
> >
> > John Lam wrote:
> > > I just finished writing the first spike for my Ruby CLR bridge
> > tonight,
> > > and
> > > I'm wondering if there might be a better (or more efficient) way to
> > add
> > > instance methods to a class object than this:
> > >
> > > class Module
> > > def const_missing(symbol)
> > > obj = Class.new
> > > obj.class_eval %{
> > > def initialize
> > > ...
> > > end
> > >
> > > def method_missing(name, *params)
> > > ...
> > > end
> > > }
> > > const_set(symbol, obj)
> > > end
> > > end
> >
> > Not really, except for using define_method (which has
> > some limitations that would probably make it unsuitable
> > for a #method_missing implementation). The 'Class methods'
> > thread had pretty much this exact implementation..
> >
> > Perhaps some sort of a prototype-based approach?
> >
> > > Thanks,
> > > -John
> > > http://www.iu...
> > >
> > > PS If you're wondering what the code in the ... blocks do, read my
> > > write-up
> > > of this code at:
> > > http://www.iu.../articles/2005/12/14/hello-rubyclr
> >
> >
> > E
> >
> > --
> > Posted via http://www.ruby-....
> >
> >
>
>

Robert Klemme

12/15/2005 10:35:00 AM

0

John Lam wrote:
> I just finished writing the first spike for my Ruby CLR bridge
> tonight, and I'm wondering if there might be a better (or more
> efficient) way to add instance methods to a class object than this:
>
> class Module
> def const_missing(symbol)
> obj = Class.new
> obj.class_eval %{
> def initialize
> ...
> end
>
> def method_missing(name, *params)
> ...
> end
> }
> const_set(symbol, obj)
> end
> end

class Module
def const_missing(symbol)
obj = Class.new do
def initialize
...
end

def method_missing(name, *params)
...
end
end
const_set(symbol, obj)
end
end

Note that this might have adversary effects on other code if consts spring
into existence just like that.

Kind regards

robert

John Lam

12/15/2005 3:00:00 PM

0

On 12/15/05, Robert Klemme <bob.news@gmx.net> wrote:
>
> Note that this might have adversary effects on other code if consts spring
> into existence just like that.
>

I trimmed most of the code out of that example for clarity, but there will
be a bunch of code that will looks up valid types to instantiate and will
punt to an old_method_missing call if the constant name is an invalid type.

Thanks for the constructor block suggestion - I did have a version sometime
last night that used that feature, but I can't recall why I changed it.

Cheers,
-John
http://www.iu...

John Lam

12/15/2005 3:14:00 PM

0

Thanks for the suggestion, Brian.

The code in method_missing will use reflection to generate the shim on the
fly, so I don't need to keep a list of methods that have been generated. The
shim is added as an instance method to the class object, so subsequent calls
will always go via the shim and not via method_missing.

Cheers,
-John
http://www.iu...