Using a module at the toplevel doesn't work

Hi,

路路路

In message "Re: using a module at the toplevel doesn't work" on Tue, 22 Aug 2006 14:05:06 +0900, "Trans" <transfire@gmail.com> writes:

As you can see my particlar 'test' example will cause an infinite loop
because the toplevel definition is being added to all objects. :frowning:

But they are private by default, so that 1.9 send will call
method_missing if you specify the explicit receiver.

聽聽聽聽聽聽聽聽聽聽聽聽聽聽matz.

Logan Capaldo wrote:

You are over simplifying Trans.'s problem.

Yea Pit, why are you doing that? :wink:

He wants dynamic generated
methods scoped to a module, or optionally scoped to the top level.
You can't use #define_method at the top level because instances don't
respond to it. You can't use the toplevel singleton class as I
suggested because a) it's a pain in the neck and b) it doesn't
inherit the right way.

Trans, what about:

# Warning evilness ensuing:

def main.define_method(*args, &block)
聽聽聽Kernel.module_eval{ define_method(*args, &block) }
end

That's basically what I ended up doing:

聽聽def define_method( meth, &block )
聽聽聽聽Object.class_eval do
聽聽聽聽聽聽define_method( meth, &block )
聽聽聽聽聽聽private meth
聽聽聽聽end
聽聽end

聽聽def ancestors
聽聽聽聽Object.ancestors
聽聽end

But as I was saying about the instance variables, it not quite that
simple. I still had to build exceptions into the module code. I just
tried to factor these down to the fewest points of departure as
possible. So I end up with a few areas like this:

聽聽$main = self

聽聽def instance_task_table
聽聽聽聽if self == $main
聽聽聽聽聽聽Object.instance_task_table
聽聽聽聽else
聽聽聽聽聽聽@instance_task_table ||= {}
聽聽聽聽end
聽聽end

and

聽聽cont = (self == $main ? Object : self )

Certainly not simple. But so far it appears to be working. I just hope
I've got all the namespace dicing covered.

Thanks,
T.

Yukihiro Matsumoto wrote:

Hi,

>As you can see my particlar 'test' example will cause an infinite loop
>because the toplevel definition is being added to all objects. :frowning:

But they are private by default, so that 1.9 send will call
method_missing if you specify the explicit receiver.

Ah, okay so fixing my toplevel #define_method to privatize the method
should do the trick, at least in my case, I see. Thanks. Of course,
just my luck, I also need 1.9's #send that doesn't invoke private
methods now! :wink: How do I get around that in 1.8 again?

So #private saves the situation. Hmm... Still, the subtleties involved
here make me wonder, is it worth it? Has the embuing of toplevel
methods throughout all objects proven of significant worth? I knwo I
have never intentially created a toplevel method with the intended
effect of adding it to all objects. And Mathew makes another good case.

Thanks,
T.

路路路

In message "Re: using a module at the toplevel doesn't work" > on Tue, 22 Aug 2006 14:05:06 +0900, "Trans" <transfire@gmail.com> writes:

Trans wrote:

How do I get around that in 1.8 again?

To answer my own question:

聽聽聽聽聽聽聽聽eval %{ Script.#{type}(*args, &data) }

T.

For his case, replace do_test as

聽聽聽def self.do_test
聽聽聽聽聽self.test
聽聽聽end
聽聽聽聽聽聽聽聽聽聽聽聽聽聽matz.

路路路

In message "Re: using a module at the toplevel doesn't work" on Tue, 22 Aug 2006 22:20:05 +0900, "Trans" <transfire@gmail.com> writes:

And Mathew makes another good case.

Yukihiro Matsumoto wrote:

>And Mathew makes another good case.

For his case, replace do_test as

聽聽聽def self.do_test
聽聽聽聽聽self.test
聽聽聽end

Almost. But that's sort of reverse the situation. Will we have to add
'self.' to every call b/c there's the chance someone will define a
toplevel method when using our libs?

I think the question stands: of what significant value come from having
the toplevel add it's methods to Object?

If we have to know these subtle tricks to avoid possible gotchas, don't
you think it should be worth the effort? I don't see how it is. I don't
think a good coder is even going to utilze the fact that toplevel
methods embue all objects in the first place.

T.

路路路

In message "Re: using a module at the toplevel doesn't work" > on Tue, 22 Aug 2006 22:20:05 +0900, "Trans" <transfire@gmail.com> writes:

Almost. But that's sort of reverse the situation. Will we have to add
'self.' to every call b/c there's the chance someone will define a
toplevel method when using our libs?

You won't need to add self to every call, only to calls which may end up in method_missing. If the method is guaranteed to exist in the object or one of its ancestors self is not necessary to ensure the expected method is called. Expecting calls to self to end up in method_missing seems like a pretty specialized case...

Matthew

Matthew Johnson wrote:

> Almost. But that's sort of reverse the situation. Will we have to add
> 'self.' to every call b/c there's the chance someone will define a
> toplevel method when using our libs?

You won't need to add self to every call, only to calls which may end
up in method_missing. If the method is guaranteed to exist in the
object or one of its ancestors self is not necessary to ensure the
expected method is called. Expecting calls to self to end up in
method_missing seems like a pretty specialized case...

Sure. All of this is a specialized case. It's a specialized case to use
the toplevel to purposefully add methods to Object. Toplevel methods
aren't that common in the first place, except in one-off scripts. But
if you actaully are utilizng the toplevel, for instance in mycase where
end-users are writting mini task scripts, then these specialized cases
come to bare strongly.

So far his is what I have had to deal with:

聽聽1. Manually add #define_method, #ancestors, &c. to proxy to Object
class.
聽聽2. Be careful b/c Toplevel and Object class 'self' can get mixed-up.
聽聽3. Avoid using #send if you're utilizing method_missing (util 1.9)
聽聽4. Add 'self.' prefix to internal methods if purposefully invoking
method_missing.

And I wouldn't be suprised if their are others.

So it's not that this is a huge issue, obviously. But why have these
issues at all if it's completely and easily avoidable? Using a self
extended module (Main) for the toplevel avoids all of this. And if, for
some reason, one needs to add their top level methods to all objects,
'class Object; include Main; end' is a very simple solution.

T.

s/their/there/

My grandmother hates it when I do that :wink:

T.

Also, irb screws it up:

聽聽irb(main):001:0> def x ; "x" ; end
聽聽=> nil
聽聽irb(main):002:0> Object.private_instance_methods(false).sort
聽聽=> ["initialize", "irb_binding"]
聽聽irb(main):003:0> Object.public_instance_methods(false).sort
聽聽=> ["x"]

T.

Hi,

路路路

In message "Re: using a module at the toplevel doesn't work" on Thu, 24 Aug 2006 07:50:13 +0900, "Trans" <transfire@gmail.com> writes:

Also, irb screws it up:

Yes, it is a irb's known bug.

聽聽聽聽聽聽聽聽聽聽聽聽聽聽matz.