defining methods dynamically?

Discussion in 'Ruby' started by Kenneth McDonald, Aug 2, 2007.

  1. 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
     
    Kenneth McDonald, Aug 2, 2007
    #1
    1. Advertising

  2. Kenneth McDonald

    Guest

    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

    --
    * Books:
    RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
    RUBY FOR RAILS (http://www.manning.com/black)
    * Ruby/Rails training
    & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
     
    , Aug 2, 2007
    #2
    1. Advertising

  3. Kenneth McDonald

    Peña, Botp Guest

    fr: Kenneth McDonald [mailto:] :
    # Having looked through the Class and Method rdoc, and the Reflection=20
    # section of Pickaxe, and still not seeing anything (even though it was=20
    # probably right in front of my nose), I'm forced to fall on=20
    # the mercy of=20
    # strangers and ask...how does one add a method to a class while the=20
    # 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 =3D 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 =3D <<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 =3D 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
     
    Peña, Botp, Aug 2, 2007
    #3
  4. Kenneth McDonald

    vasudevram Guest

    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
     
    vasudevram, Aug 2, 2007
    #4
  5. Kenneth McDonald

    Guest

    Hi --

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

    > On Aug 01, 2007, at 21:49 , 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?


    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

    --
    * Books:
    RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
    RUBY FOR RAILS (http://www.manning.com/black)
    * Ruby/Rails training
    & consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
     
    , Aug 2, 2007
    #5
  6. Kenneth McDonald

    Peña, Botp Guest

    From: Wayne E. Seguin [mailto:] :
    # That makes complete sense.=20

    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!=20

    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 =3D 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 =3D %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
     
    Peña, Botp, Aug 3, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jasper Pearlman

    Defining methods outside of script tags

    Jasper Pearlman, Aug 16, 2004, in forum: ASP .Net
    Replies:
    3
    Views:
    351
  2. johny smith
    Replies:
    8
    Views:
    419
    Peter Koch Larsen
    Jul 2, 2004
  3. Kenneth McDonald
    Replies:
    5
    Views:
    126
    Kenneth McDonald
    Aug 5, 2007
  4. Venkat Bagam

    defining methods dynamically

    Venkat Bagam, Oct 30, 2007, in forum: Ruby
    Replies:
    10
    Views:
    210
  5. Kenneth McDonald
    Replies:
    5
    Views:
    322
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page