using a module at the toplevel doesn't work

M

Matthew Johnson

|Well, is there anyway to turn toplevel effects on Object off? I
have a
|real scenario where it causes issues.
|
| module X
| def self.method_missing( name, *args )
| if name ...
| if require 'foo'
| send( name, *args )
| ...
|
|Now if some method is defined at toplevel it can screw up my module X
|lazy loader.

Can you show me working (well, I mean non-working) example. I am not
sure how above example relates to toplevel effects.

matz.

I would imagine something like this is being described:

def test
puts "didn't work as desired"
end

module X
def self.method_missing name, *args
# check name and require file containing the method
puts "works as desired: resending message #{name}"
end
def self.do_test
test
end
end

X.do_test

Of course if you try X.test of self.test inside of X we get "works as
desired..."

Matthew
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: using a module at the toplevel doesn't work"

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

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

matz.
 
T

Trans

Yukihiro said:
Hi,

In message "Re: using a module at the toplevel doesn't work"

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

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! ;) 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.
 
Y

Yukihiro Matsumoto

In message "Re: using a module at the toplevel doesn't work"

|And Mathew makes another good case.

For his case, replace do_test as

def self.do_test
self.test
end
matz.
 
T

Trans

Yukihiro said:
In message "Re: using a module at the toplevel doesn't work"

|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.
 
M

Matthew Johnson

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
 
T

Trans

Matthew said:
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.
 
T

Trans

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.
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: using a module at the toplevel doesn't work"

|Also, irb screws it up:

Yes, it is a irb's known bug.

matz.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,787
Messages
2,569,629
Members
45,332
Latest member
LeesaButts

Latest Threads

Top