Issue #6609 has been updated by drbrain (Eric Hodel).


trans (Thomas Sawyer) wrote:
> > There are no method calls on the top-level object in this example. Nothing is delegated.
> 
> I've been able to find the code for three methods which delegate:
> 
> eval.c:      rb_define_singleton_method(rb_vm_top_self(), "include", top_include, -1);
> vm_method.c: rb_define_singleton_method(rb_vm_top_self(), "public", top_public, -1);
> vm_method.c: rb_define_singleton_method(rb_vm_top_self(), "private", top_private, -1);

These aren't delegated, they are singleton methods which add behavior to make top-self more useful.

rb_define_singleton_method() is the same as:

  o = Object.new
  def o.include(*) end

> I understand what you are saying about def now, b/c of how Ruby handles def in other defs. Actually, I always thought that was little odd. I know others have suggested that maybe inner defs should be local to the method itself. Not that it's a big deal --I think that's very minor thing. But now I see how one oddity became the result of another.
> 
> > Again, define_method only exists on Module and its subclasses.
> 
> If one is able to use `def` in a context, does in not stand to reason that one could also use `define_method`? Since #define_method is, after all, the means given us to create methods dynamically (without resorting to eval).

No, due to what you said above ("how Ruby handles def in other defs").  Also:

  ruby -e 'class C; def make; define_method(:foo) { } end; end; C.new.make'

> > That people have done bad things is not a compelling reason.
> 
> That is but *one* (good) reason.

The current behavior is bad for some things and good for others.

Also, since the top-self is one of the first objects new rubyists interact with, changing the behavior of top-self may break introductory tutorials on ruby.  Many, many people use it so we must be very careful when changing it.

> In fact, have you considered the other merits I mentioned? Arguing against this solely on the basis that the top-level is what the top-level is, pretty much misses the point to *improve* upon what it is.

It is easy to create a clean-room DSL evaluation context now:

  m = Module.new do
    extend SomeDSL
  end

  m.instance_eval File.read 'dsl_file.rb'

So the improvement is a convenience for a very rare use at the expense of a change every rubyist needs to learn about.


----------------------------------------
Feature #6609: Toplevel as self extended module
https://bugs.ruby-lang.org/issues/6609#change-27350

Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee: 
Category: core
Target version: 2.0.0


As promised sometime back here is my proposal that Toplevel object become a self-extended module instead of the current partial Object class proxy.

I have written about it in a blog post: http://trans.github.com/2012/06/17/kill-the-proxy-and-save-toplevel.html

In summary the basic idea is to have a special toplevel namespace that is self-extended, e.g.

  module Toplevel
    extend self
  end

in which all toplevel code is evaluated. 

Definitions at the toplevel would no longer inject into Object class. This frees up the toplevel to be used for general purpose DSL "batch" scripting. What I mean by that is that one can create a DSL, load it in to toplevel and then evaluate scripts based on it simply by load/require and without fret that the code loaded in will infect Object if it defines it's own methods.

Conceptually the idea of self-extended module is much simpler than current proxy object --there is really nothing special to understand about it since it is just a module like any other module.

With regard to backward compatibility, the only programs that would be effected are any that defined a toplevel method fully expecting it to add a method to Object. But those will be very rare since it is generally considered bad form to do that. (And of course the simple fix is to wrap the method in the proper `class Object private ... end` code.



-- 
http://bugs.ruby-lang.org/