Why can't I get on Top?

More Toplevel blow:

  $toplevel = self
  module Test
    def self.included( base )
      p base == $toplevel
    end
  end
  include Test

Produces:

  false

:frowning:

T.

Trans wrote:

Produces:

  false

That's correct. In that case self is an *instance* of Object...

module Test
  def test
    puts 'hi'
  end
end
class << self
  include Test
end
test

...but Module#included tells you the module or class of the including
scope; it doesn't pass the instance itself.

Regards,
Jordan

More Toplevel blow:

  $toplevel = self
  module Test
    def self.included( base )
      p base == $toplevel
    end
  end
  include Test

Produces:

  false

:frowning:

I wonder if the powers that be would consider adding some additional
hooks if they don;t want to make the top-level an extended self module.

(e.g:

alias toplevel_include include
def include(mod)
  toplevel_include( mod )
  mod.included( self )
end

I don't really like that actually. Trans, consider my vote added in
favor to "Make the toplevel a self-extended module". It just seems so
much more useful and cleaner without this silly proxying.

···

On Mon, Oct 02, 2006 at 09:35:11AM +0900, Trans wrote:

T.

Hi --

Trans wrote:

Produces:

  false

That's correct. In that case self is an *instance* of Object...

module Test
def test
   puts 'hi'
end
end
class << self
include Test
end
test

...but Module#included tells you the module or class of the including
scope; it doesn't pass the instance itself.

Yes it does: the instance itself *is* a Module (or Class) :slight_smile: There's
no translation or looking up necessary:

   class C
     include M # the method "include" is called on the object C
   end

The top level is a bit anomalous: 'self' is not a Module or Class, but
it does some proxying for Object. So if you do:

   include M

at the top level, it's as if you'd done:

   class Object
     include M
   end

David

···

On Mon, 2 Oct 2006, MonkeeSage wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Jeffrey Schwab wrote:

module Test
     def self.included( base )
         p base == $toplevel
     end
end

class << self

     # $toplevel has to be set in here,
     # where it can really refer to the
     # including object.

     $toplevel = self
     include Test
end

In your example you are controlling the inclusion from the start.
That's missing the point. The #included callback catches the inclusion
of a module and _reacts_ to that. The module is a resuable lib that an
end-user/programmer may well include at the toplevel and the module
should just work. Otherwise one has to document: "IMPORTANT: don't
include at toplevel, It won't work...."

But you also may not realize that methods defined at the toplevel do
not go to the singleton. They go to Object itself. So really your
example should be:

  class Object
      $toplevel = self
      include Test
  end

But you are getting a false positive, since:

  module NotTheTopLevel
      $toplevel = self
      include Test
  end

works too.

T.

Hi Trans,

How about a workaround for now? Something like:

class << self
  def include(mod)
    self.extend(mod)
    if in_toplevel?
      p 'Do NOT use me from toplevel'
    end
  end
end

module NoTopLevel
  def in_toplevel?
    self.to_s == 'main'
  end
end

include NoTopLevel

Regards,
Jordan

dblack@wobblini.net wrote:

The top level is a bit anomalous: 'self' is not a Module or Class, but
it does some proxying for Object. So if you do:

   include M

at the top level, it's as if you'd done:

   class Object
     include M
   end

That's what I was trying to say. :wink:

But main is an *instance* of Object, isn't it? At least, it acts like
one. Thus singleton methods:

class << self
  include Test
end

And class membership:

p self.class

Regards,
Jordan

MonkeeSage wrote:

Hi Trans,

How about a workaround for now? Something like:

class << self
  def include(mod)
    self.extend(mod)
    if in_toplevel?
      p 'Do NOT use me from toplevel'
    end
  end
end

module NoTopLevel
  def in_toplevel?
    self.to_s == 'main'
  end
end

include NoTopLevel

Well, let me show you what I'm actually doing:

  module Taskable
    def self.included( base )
      if base.toplevel?
        require 'main_as_module.rb'
      end
    end
  end

main_as_module.rb is actually a bit of code that will add every module
method there is to toplevel (ie. main). So you see I'm actually trying
to selectively mitigate the issue were talking about. I could just
require this lib no matter what and be done with it, but I thought it
would be better if I only included it if it is needed --no sense in
loading code that's not used. But it looks like I don't have much
choice. However, I did manage this work-around:

  module Taskable
    def self.included( base )
      if base == Object
        require 'main_as_module.rb'
      end
    end
  end

That catches it, although it also catches when Taskable is included in
Object too. But that's only one exception that won't cause any harm, so
it's an accecptable work around.

T.

dblack@wobblini.net wrote:

The top level is a bit anomalous: 'self' is not a Module or Class, but
it does some proxying for Object. So if you do:

Right. So how does one catch if a module is included at the toplevel
then?

MonkeeSage wrote:

But main is an *instance* of Object, isn't it? At least, it acts like
one. Thus singleton methods:

Yes, but so is everything.

I really wish someone would tell me what's wrong with a self extended
module for toplevel instead of this silly proxy of Object.

T.

Trans wrote:

That catches it, although it also catches when Taskable is included in
Object too. But that's only one exception that won't cause any harm, so
it's an accecptable work around.

Right on. I just realized that my last suggestion was retarded anyhow,
since in_toplevel? *had* to be true, always, since I was only
overriding #include as a singleton method of the main instance. Doh
(guess I'm still not the sharpest tool!).

Regards,
Jordan

Trans wrote:

Yes, but so is everything.

Hmmm...I'm not the sharpest tool in the shed, but I don't think that is
correct. There are first-order objects like classes and modules.
Normally #included gets the class or module object itself, not an
instance. At least that's how I've always thought it worked.

module Test
  def self.included(base)
    p base.instance_of?(C) # => false
    base.module_eval { # <- extends the actual class, not an instance
      def m
        puts 'Howdy do'
      end
    }
  end
end
class C
  include Test
end
C.new.m

Regards,
Jordan

The base level in Ruby runs in the context of an instance of Object.
When you add base level methods you're actually adding those methods to
the eigenclass of the main object. The main object in essence is an
instance of its eigenclass and the eigenclass is a subclass of the
Object class. You can do this with any Ruby object (except Fixnums,
which is an annoying inconsistency):

irb(main):010:0> a = "Frog"
=> "Frog"

irb(main):011:0> def a.double
irb(main):012:1> self * 2
irb(main):013:1> end
=> nil

irb(main):014:0> a.double
=> "FrogFrog"

irb(main):015:0> b = "Camel"
=> "Camel"

irb(main):016:0> b.double
NoMethodError: undefined method `double' for "Camel":String
        from (irb):16

Note that the original String class isn't affected - the method has
been added to the eigenclass of object a.

MonkeeSage wrote:

···

from :0

Trans wrote:
> Yes, but so is everything.

Hmmm...I'm not the sharpest tool in the shed, but I don't think that is
correct. There are first-order objects like classes and modules.
Normally #included gets the class or module object itself, not an
instance. At least that's how I've always thought it worked.

module Test
  def self.included(base)
    p base.instance_of?(C) # => false
    base.module_eval { # <- extends the actual class, not an instance
      def m
        puts 'Howdy do'
      end
    }
  end
end
class C
  include Test
end
C.new.m

Regards,
Jordan

Hi --

The base level in Ruby runs in the context of an instance of Object.
When you add base level methods you're actually adding those methods to
the eigenclass of the main object. The main object in essence is an
instance of its eigenclass and the eigenclass is a subclass of the
Object class. You can do this with any Ruby object (except Fixnums,
which is an annoying inconsistency):

The singleton class/object relationship isn't quite an instance one;
it's a little more "phantom"-like. It doesn't add a real level to the
"family tree"; an object is still an instance of the thing it was an
instance of before:

class C; end
class D < C; end

d = D.new
sing = class << d; self; end

p D.new.instance_of?(C) # false
p D.new.instance_of?(D) # true
p D.new.instance_of?(sing) # false

So thinking of the singleton class as a subclass of the object's class
might be a little misleading, since the object still relates to its
"birth class" at only one level of remove.

David

···

On Mon, 2 Oct 2006, Timothy Goddard wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Timothy Goddard wrote:

The base level in Ruby runs in the context of an instance of Object.
When you add base level methods you're actually adding those methods to
the eigenclass of the main object.

That's not correct. The methods are being added to Object itself. Main
is just a proxy. The methods is has related to defining and looking up
methods just reroute to Object.

  def x; end
  p Object.private_instance_methods(false)
  => ['initialize', 'x']

To add to the toplevel pot:

  def x; end
  respond_to?(:x)
  => false

(I know, b/c it's private method, but still.)

T.

Hi --

class C; end
class D < C; end

d = D.new
sing = class << d; self; end

p D.new.instance_of?(C) # false
p D.new.instance_of?(D) # true
p D.new.instance_of?(sing) # false

So thinking of the singleton class as a subclass of the object's class
might be a little misleading, since the object still relates to its
"birth class" at only one level of remove.

Of course, but what I am puzzeled about is, why you use #instance_of?, well
not really, because that was how the argument began.
As a matter of fact let me be more humble :wink:
I am afraid I missed something basic in the discussion, because to my
understanding #instance_of? is irrelevant and #is_a?
is what we are interested in, no? (obviously no ;).
Thx
Robert

···

On 10/2/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Hi --

···

On Mon, 2 Oct 2006, Robert Dober wrote:

On 10/2/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

Hi --

class C; end
class D < C; end

d = D.new
sing = class << d; self; end

p D.new.instance_of?(C) # false
p D.new.instance_of?(D) # true
p D.new.instance_of?(sing) # false

So thinking of the singleton class as a subclass of the object's class
might be a little misleading, since the object still relates to its
"birth class" at only one level of remove.

Of course, but what I am puzzeled about is, why you use #instance_of?, well
not really, because that was how the argument began.
As a matter of fact let me be more humble :wink:
I am afraid I missed something basic in the discussion, because to my
understanding #instance_of? is irrelevant and #is_a?
is what we are interested in, no? (obviously no ;).

I was responding to Timothy's description of the default object main
as an instance of its singleton class. My point was that the
relationship between an object and its singleton class is not actually
defined by Ruby as a class-instance relationship, though of course it
is very similar to such a relationship in many ways.

David

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org

Hi --

>>
>> Hi --
>>
>> class C; end
>> class D < C; end
>>
>> d = D.new
>> sing = class << d; self; end
>>
>> p D.new.instance_of?(C) # false
>> p D.new.instance_of?(D) # true
>> p D.new.instance_of?(sing) # false
>>
>> So thinking of the singleton class as a subclass of the object's class
>> might be a little misleading, since the object still relates to its
>> "birth class" at only one level of remove.
>
> Of course, but what I am puzzeled about is, why you use #instance_of?,
well
> not really, because that was how the argument began.
> As a matter of fact let me be more humble :wink:
> I am afraid I missed something basic in the discussion, because to my
> understanding #instance_of? is irrelevant and #is_a?
> is what we are interested in, no? (obviously no ;).

I was responding to Timothy's description of the default object main
as an instance of its singleton class.

Yes I pointed that out...

  My point was that the

relationship between an object and its singleton class is not actually
defined by Ruby as a class-instance relationship, though of course it
is very similar to such a relationship in many ways.

... but I got confused with the original concept, I did not realize that you
drifted OT, which is not a bad thing.
Your clarifications will save me some time as I was intrigued in which way
the
instance_of_ness of the main object would be relevant, and I guess it is
not.
Thx
Robert

David

···

On 10/2/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

On Mon, 2 Oct 2006, Robert Dober wrote:
> On 10/2/06, dblack@wobblini.net <dblack@wobblini.net> wrote:

--
                   David A. Black | dblack@wobblini.net
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] Ruby for Rails | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org