Followup question on defining methods dynamically

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

  1. Simple example that doesn't work:

    ----------------
    module Test
    p "Testing"
    eval("def foo\np 'OK'\nend")
    foo
    end
    ----------------

    'foo' does not get defined in a place where it can be found by the call
    on foo, and I get an error. However, when I execute the two lines

    eval("def foo\np 'OK'\nend")
    foo

    in IRB, everything works. I'm guessing that this is a namespace problem,
    but can't see why it would be. Then again, I'm accustomed to the Python
    namespace model, and still don't understand all of the ways in which the
    Ruby model is different.

    Thanks for any suggestions,
    Ken
    Kenneth McDonald, Aug 3, 2007
    #1
    1. Advertising

  2. Kenneth McDonald

    Guest

    Hi --

    On Sat, 4 Aug 2007, Kenneth McDonald wrote:

    > Simple example that doesn't work:
    >
    > ----------------
    > module Test
    > p "Testing"
    > eval("def foo\np 'OK'\nend")
    > foo
    > end
    > ----------------
    >
    > 'foo' does not get defined in a place where it can be found by the call on
    > foo, and I get an error. However, when I execute the two lines
    >
    > eval("def foo\np 'OK'\nend")
    > foo
    >
    > in IRB, everything works. I'm guessing that this is a namespace problem, but
    > can't see why it would be. Then again, I'm accustomed to the Python namespace
    > model, and still don't understand all of the ways in which the Ruby model is
    > different.


    Your first example is essentially doing this:

    module Test
    def foo
    p "OK"
    end

    foo
    end

    When you define an instance method inside a module, you're defining it
    for the future use of objects with that module in their ancestry:

    class C
    include Test
    end

    C.new.foo # OK


    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 3, 2007
    #2
    1. Advertising

  3. Do modules not execute their own code (such as the 'p "Testing"') below
    in their own namespace, then? I'm doing something that's not at all
    object-oriented, and simply want to ensure that a bunch of methods don't
    leak out into the global namespace. One module will define those
    methods, and other modules (not classes, unless I really have to hack it
    that way) will use the first module, eg.

    module Test
    p "Testing"
    eval("def foo\np 'OK'\nend")
    end

    module Run
    include Test
    foo
    end

    The above doesn't work, for the reasons you gave, but I still don't
    understand the semantics of why not, I'm afraid. No doubt my Python way
    of thinking. In Python, the equivalent code would create two modules,
    Test and Run, which are effectively just hashmaps mapping names to
    objects. The eval would define a 'foo' object in Test, so there would
    exist a function Test.foo. The include statement in Run (equivalent to
    Python's "from Test import *" I believe) would cause all names in Test
    to be imported into Run, resulting in a 'foo' entry in the Run hashmap;
    this would be Run.foo. Finally, code run within a module always has
    access to the module's namespace (hashmap) for variable lookup, so the
    call on 'foo' within Run would find 'Run.foo' and execute it.

    Now, since that interpretation is obviously incorrect in Ruby, could
    someone provide details as to what is actually going on? If possible, I
    prefer explanations of the 'behind-the-scenes' stuff--how variables are
    looked up, namespaces are defined, etc., as understanding the background
    mechanisms will then make everything else pretty easy.

    Thanks,
    Ken


    wrote:
    > Hi --
    >
    > On Sat, 4 Aug 2007, Kenneth McDonald wrote:
    >
    >> Simple example that doesn't work:
    >>
    >> ----------------
    >> module Test
    >> p "Testing"
    >> eval("def foo\np 'OK'\nend")
    >> foo
    >> end
    >> ----------------
    >>
    >> 'foo' does not get defined in a place where it can be found by the
    >> call on foo, and I get an error. However, when I execute the two lines
    >>
    >> eval("def foo\np 'OK'\nend")
    >> foo
    >>
    >> in IRB, everything works. I'm guessing that this is a namespace
    >> problem, but can't see why it would be. Then again, I'm accustomed to
    >> the Python namespace model, and still don't understand all of the
    >> ways in which the Ruby model is different.

    >
    > Your first example is essentially doing this:
    >
    > module Test
    > def foo
    > p "OK"
    > end
    >
    > foo
    > end
    >
    > When you define an instance method inside a module, you're defining it
    > for the future use of objects with that module in their ancestry:
    >
    > class C
    > include Test
    > end
    >
    > C.new.foo # OK
    >
    >
    > David
    >
    Kenneth McDonald, Aug 4, 2007
    #3
  4. Kenneth McDonald

    Guest

    Hi -

    On Sat, 4 Aug 2007, Kenneth McDonald wrote:

    > Do modules not execute their own code (such as the 'p "Testing"') below in
    > their own namespace, then?


    They do execute their own code, but the code being executed is an
    instance method definition. Like 'p "testing"', the method definition
    gets executed when it's encountered. But it still has a particular
    effect, namely creating an instance method for objects that use this
    module.

    > I'm doing something that's not at all
    > object-oriented, and simply want to ensure that a bunch of methods don't leak
    > out into the global namespace. One module will define those methods, and
    > other modules (not classes, unless I really have to hack it that way) will
    > use the first module, eg.
    >
    > module Test
    > p "Testing"
    > eval("def foo\np 'OK'\nend")
    > end
    >
    > module Run
    > include Test
    > foo
    > end
    >
    > The above doesn't work, for the reasons you gave, but I still don't
    > understand the semantics of why not, I'm afraid. No doubt my Python way of
    > thinking.

    [...]
    > Now, since that interpretation is obviously incorrect in Ruby, could someone
    > provide details as to what is actually going on? If possible, I prefer
    > explanations of the 'behind-the-scenes' stuff--how variables are looked up,
    > namespaces are defined, etc., as understanding the background mechanisms will
    > then make everything else pretty easy.


    Basically, it works like this: every time you send a message to an
    object, the object searches along a lookup path consisting of classes
    and modules, looking for a corresponding method. The path includes
    the object's class, and also any modules that the class includes, and
    modules included by those modules, etc.

    Modules are themselves objects. That means that when you send a
    message to a module, it looks for that method in its lookup path.
    However, a module does not lie in its own lookup path (unless you
    include it in itself).

    A module (and a class) has a kind of dual identity: it's a repository
    of instance methods for other objects, and it's also an object in its
    own right. These two roles are fairly strictly delineated. You can't
    do this:

    class C
    def x
    end
    end

    C.x

    because x is defined for the use of instances of C, not C itself.
    Similarly, you can't do this:

    module M
    def x
    end
    end

    M.x

    for the same reason. And this:

    module M
    def x
    end

    x
    end

    is exactly the same: you're sending the message "x" to the module
    object M, but that object doesn't have an x method.


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

    Robert Dober Guest

    On 8/3/07, <> wrote:
    > Hi -
    >
    > On Sat, 4 Aug 2007, Kenneth McDonald wrote:
    >

    <snip>
    > Modules are themselves objects. That means that when you send a
    > message to a module, it looks for that method in its lookup path.
    > However, a module does not lie in its own lookup path (unless you
    > include it in itself).

    Hmm I think it might be useful to clarify this a little bit
    when David talks about including a module in itself he means including
    it into the lookup array of itself, this is done with extend, not with
    include.
    As a matter of fact you cannot do this:
    module A
    def a; 110 end
    include self
    end
    it does not make sense either, right, however you can do this of course
    module A
    def a; 132 end
    extend self
    p a
    end
    a different way to do this is
    modue A
    def a; 222 end # that is a nice way to say 42 ;)
    module_function :a
    end
    Now a is not available as *public* instance method anymore it becomes *private*.

    Cheers
    Robert



    --
    [...] as simple as possible, but no simpler.
    -- Attributed to Albert Einstein
    Robert Dober, Aug 4, 2007
    #5
  6. Yep, it's the extend that did it for me.

    I now have a much better idea of Ruby lookup mechanisms :)

    Many thanks to both you and David,
    Ken



    Robert Dober wrote:
    > On 8/3/07, <> wrote:
    >
    >> Hi -
    >>
    >> On Sat, 4 Aug 2007, Kenneth McDonald wrote:
    >>
    >>

    > <snip>
    >
    >> Modules are themselves objects. That means that when you send a
    >> message to a module, it looks for that method in its lookup path.
    >> However, a module does not lie in its own lookup path (unless you
    >> include it in itself).
    >>

    > Hmm I think it might be useful to clarify this a little bit
    > when David talks about including a module in itself he means including
    > it into the lookup array of itself, this is done with extend, not with
    > include.
    > As a matter of fact you cannot do this:
    > module A
    > def a; 110 end
    > include self
    > end
    > it does not make sense either, right, however you can do this of course
    > module A
    > def a; 132 end
    > extend self
    > p a
    > end
    > a different way to do this is
    > modue A
    > def a; 222 end # that is a nice way to say 42 ;)
    > module_function :a
    > end
    > Now a is not available as *public* instance method anymore it becomes *private*.
    >
    > Cheers
    > Robert
    >
    >
    >
    >
    Kenneth McDonald, Aug 5, 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. mbs

    Followup: Newbee Question

    mbs, Apr 6, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    288
    James Hancock
    Apr 6, 2004
  2. Darrel
    Replies:
    5
    Views:
    1,261
    Karl Seguin
    Nov 11, 2004
  3. johny smith
    Replies:
    8
    Views:
    411
    Peter Koch Larsen
    Jul 2, 2004
  4. Kenneth McDonald

    defining methods dynamically?

    Kenneth McDonald, Aug 2, 2007, in forum: Ruby
    Replies:
    5
    Views:
    109
    Peña, Botp
    Aug 3, 2007
  5. Venkat Bagam

    defining methods dynamically

    Venkat Bagam, Oct 30, 2007, in forum: Ruby
    Replies:
    10
    Views:
    206
Loading...

Share This Page