Forum: Ruby defining methods dynamically?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Kenneth McDonald (Guest)
on 2007-08-02 05:43
(Received via mailing list)
Having looked through the Class and Method rdoc, and the Reflection
section of Pickaxe, and still not seeing anything (even though it was
probably right in front of my nose), I'm forced to fall on the mercy of
strangers and ask...how does one add a method to a class while the
program is running?

Thanks,
Ken
unknown (Guest)
on 2007-08-02 05:50
(Received via mailing list)
Hi --

On Thu, 2 Aug 2007, Kenneth McDonald wrote:

> Having looked through the Class and Method rdoc, and the Reflection section
> of Pickaxe, and still not seeing anything (even though it was probably right
> in front of my nose), I'm forced to fall on the mercy of strangers and
> ask...how does one add a method to a class while the program is running?

There's actually no other way to do it :-)  But I think what you're
looking for is #define_method, which lets you define methods with
dynamically-determined names and also gives you a way to flatten the
variable scope of a method definition.

For example:

   str = "greet"
   c = Class.new
   c.class_eval { define_method(str) { puts "Hello" } }

   c.new.greet    # Hello


David
Peña, Botp (Guest)
on 2007-08-02 06:33
(Received via mailing list)
fr: Kenneth McDonald [mailto:removed_email_address@domain.invalid] :
# Having looked through the Class and Method rdoc, and the Reflection
# section of Pickaxe, and still not seeing anything (even though it was
# probably right in front of my nose), I'm forced to fall on
# the mercy of
# strangers and ask...how does one add a method to a class while the
# program is running?

this is just one stupid example,

C:\temp>cat test.rb
puts "i'm running..."

class C
   puts "i'm running... inside class"
end

puts "i'm running..."

c = C.new

puts c.meth rescue puts "no c.meth yet, so this will print"

class C
   puts "i'm running... inside class; creating method meth now"
   def meth
      "yeow!"
   end
end

puts "i'm running..."
puts c.meth rescue puts "meth will run now, so this will not print"

puts "i'm running..."
puts c.meth2 rescue puts "method meth2 not yet defined"

puts "let us put the creation on a string..."
puts "i'm running..."
s = <<CLASS
class C
   puts "i'm running... inside class; creating method second meth2 now"
   def meth2
      "hehey!"
   end
end
CLASS

puts "i'm running..."
eval(s)

puts "now meth2 will run"

puts "i'm running..."
puts c.meth2 rescue puts "meth2 will run, so this will not print"

puts "i'm running..."
puts c.meth3 rescue puts "meth3 will not run yet, so this will print"

puts "now let us put the creation of meth3 using get. i know, but this
is a stup
id example"
puts "i'm running..."
puts "pls enter a class definition in one line only:"
s = gets
eval(s)
puts "i'm running..."
puts c.meth3 rescue puts "now meth3 will run, so this will not print"
puts "i'm running..."
puts "ok"

C:\temp>ruby test.rb
i'm running...
i'm running... inside class
i'm running...
no c.meth yet, so this will print
i'm running... inside class; creating method meth now
i'm running...
yeow!
i'm running...
method meth2 not yet defined
let us put the creation on a string...
i'm running...
i'm running...
i'm running... inside class; creating method second meth2 now
now meth2 will run
i'm running...
hehey!
i'm running...
meth3 will not run yet, so this will print
now let us put the creation of meth3 using get. i know, but this is a
stupid exa
mple
i'm running...
pls enter a class definition in one line only:
class C; def meth3; "hello from meth3"; end;end
i'm running...
hello from meth3
i'm running...
ok

C:\temp>

kind regards -botp
Wayne E. Seguin (Guest)
on 2007-08-02 16:07
(Received via mailing list)
On Aug 01, 2007, at 21:49 , removed_email_address@domain.invalid wrote:
> <snip>
> There's actually no other way to do it :-)  But I think what you're
> looking for is #define_method, which lets you define methods with
> dynamically-determined names and also gives you a way to flatten the
> variable scope of a method definition.
> <snip>

David,

I do not follow what you mean by "flatten the variable scope of a
method definition".
Could you please explain what this means a bit?

Many thanks!
unknown (Guest)
on 2007-08-02 16:25
(Received via mailing list)
Hi --

On Thu, 2 Aug 2007, Wayne E. Seguin wrote:

> I do not follow what you mean by "flatten the variable scope of a method
> definition".
> Could you please explain what this means a bit?

Sure.  Let's say you want to do:

   a = 1
   class C
     def show_a
       a          # won't work
     end
   end

The definition of a won't make it into the scope of the method
definition #show_a, because both the class keyword and the def keyword
start a new local scope.

However, class_eval and define_method are both permeable, as to scope.
So you can do:

   a = 1
   class C; end
   C.class_eval { define_method(:show_a) { a } }

   C.new.show_a    # 1

The a inside the block given to define_method is the same a that I
defined in the first line.  That's what I mean by flattening the
variable scope.


David
vasudevram (Guest)
on 2007-08-02 16:27
(Received via mailing list)
Kenneth McDonald wrote:
>Having looked through the Class and Method rdoc, and the Reflection  section of Pickaxe, 
and still not seeing anything (even though it was probably right in front of my nose), I'm 
forced to fall on the mercy of strangers and ask...how does one add a method to a class 
while the program is running?

I think there are at least two ways to do it, both of which I've seen
in the Ruby Cookbook.

One uses define_method, as one of the other posters said; the other
uses module_eval, IIRC. There's also an example using module_eval in
the Pickaxe - 2nd edition.

Vasudev Ram
http://www.dancingbison.com
http://jugad.livejournal.com
http://sourceforge.net/projects/xtopdf
Wayne E. Seguin (Guest)
on 2007-08-02 16:35
(Received via mailing list)
On Aug 02, 2007, at 08:24 , removed_email_address@domain.invalid wrote:
> definition #show_a, because both the class keyword and the def keyword
>
> The a inside the block given to define_method is the same a that I
> defined in the first line.  That's what I mean by flattening the
> variable scope.
>
> David

That makes complete sense. Thank you kindly for the explanation.
Peña, Botp (Guest)
on 2007-08-03 09:04
(Received via mailing list)
From: Wayne E. Seguin [mailto:removed_email_address@domain.invalid] :
# That makes complete sense.

careful. me thinks define_method is verry different from normal ruby
methods,
 a. it flattens scope. variables just creep inside
 b. it does not check for arguments

ergo, i'd prefer define_method be renamed to define_method!

i suggest define_method should be documented clearly. it could hang
nubies, like me :)

module_eval-ing may be closer to ruby methods.

eg,

C:\family\ruby>cat test.rb
a = 1
class C; end
C.class_eval {define_method(:show_a) {a}}

# this will not err; define_method methods do not check arguments!
puts C.new.show_a(1)

# just to show difference...
class C
   def show_a2
      a
   end
end

# this will err as usual; i just put a rescue to let prg continue
puts C.new.show_a2(1) rescue puts "wrong number of args !!"

# I think module_eval is a closer match to normal methods
s = %q{def show_a(); a ; end}
C.module_eval(s)

# vars will not creep
puts C.new.show_a() rescue puts "undefined a !!"
# and args will be checked
puts C.new.show_a(1) rescue puts "wrong number of args !!"

C:\family\ruby>ruby test.rb
1
wrong number of args !!
undefined a !!
wrong number of args !!

C:\family\ruby>


kind regards -botp
This topic is locked and can not be replied to.