Amazing behavior of include module

Hi,
I do not understand how is following code working:
irb(main):001:0> module AAA
irb(main):002:1> class BBB
irb(main):003:2> end
irb(main):004:1> end
=> nil
irb(main):005:0> BBB::BBB
NameError: uninitialized constant BBB
        from (irb):5
        from /usr/local/bin/irb:12:in `<main>'
irb(main):006:0> AAA::BBB::BBB
NameError: uninitialized constant AAA::BBB::BBB
        from (irb):6
        from /usr/local/bin/irb:12:in `<main>'
irb(main):007:0> include AAA
=> Object
irb(main):008:0> BBB::BBB
=> AAA::BBB
irb(main):009:0> BBB::BBB::BBB
=> AAA::BBB
irb(main):010:0> BBB::BBB::BBB::BBB
=> AAA::BBB
irb(main):011:0> AAA::BBB::BBB::BBB
=> AAA::BBB

I thought that last four lines will not work, but they do. How is it possible?
Thank you.
Pavel Strnad

This is really quite odd to me. Especially since AAA::BBB.constants returns
an empty array. Anybody have an answer to this?

···

On Wed, Feb 2, 2011 at 11:49 AM, Pavel Strnad <pavel.strnad@fel.cvut.cz>wrote:

Hi,
I do not understand how is following code working:
irb(main):001:0> module AAA
irb(main):002:1> class BBB
irb(main):003:2> end
irb(main):004:1> end
=> nil
irb(main):005:0> BBB::BBB
NameError: uninitialized constant BBB
       from (irb):5
       from /usr/local/bin/irb:12:in `<main>'
irb(main):006:0> AAA::BBB::BBB
NameError: uninitialized constant AAA::BBB::BBB
       from (irb):6
       from /usr/local/bin/irb:12:in `<main>'
irb(main):007:0> include AAA
=> Object
irb(main):008:0> BBB::BBB
=> AAA::BBB
irb(main):009:0> BBB::BBB::BBB
=> AAA::BBB
irb(main):010:0> BBB::BBB::BBB::BBB
=> AAA::BBB
irb(main):011:0> AAA::BBB::BBB::BBB
=> AAA::BBB

I thought that last four lines will not work, but they do. How is it
possible?
Thank you.
Pavel Strnad

The short answer is:

module A
  class B
  end
end
Object.ancestors # => [Object, Kernel, BasicObject]
include A
Object.ancestors # => [Object, A, Kernel, BasicObject]

What you should do to fix this is use extend rather than include:

module A
  class B
  end
end

extend A
begin
  B # => A::B
  Fixnum::B # =>
rescue
  $! # => #<NameError: uninitialized constant Fixnum::B>
end

include A
begin
  B # => A::B
  Fixnum::B # => A::B
rescue
  $! # =>
end

I made a post about it a while back, though I was talking about this problem
with methods rather than classes
http://groups.google.com/group/ruby-talk-google/browse_thread/thread/e33422848e168c4e?fwc=2

···

On Wed, Feb 2, 2011 at 10:49 AM, Pavel Strnad <pavel.strnad@fel.cvut.cz>wrote:

Hi,
I do not understand how is following code working:
irb(main):001:0> module AAA
irb(main):002:1> class BBB
irb(main):003:2> end
irb(main):004:1> end
=> nil
irb(main):005:0> BBB::BBB
NameError: uninitialized constant BBB
       from (irb):5
       from /usr/local/bin/irb:12:in `<main>'
irb(main):006:0> AAA::BBB::BBB
NameError: uninitialized constant AAA::BBB::BBB
       from (irb):6
       from /usr/local/bin/irb:12:in `<main>'
irb(main):007:0> include AAA
=> Object
irb(main):008:0> BBB::BBB
=> AAA::BBB
irb(main):009:0> BBB::BBB::BBB
=> AAA::BBB
irb(main):010:0> BBB::BBB::BBB::BBB
=> AAA::BBB
irb(main):011:0> AAA::BBB::BBB::BBB
=> AAA::BBB

I thought that last four lines will not work, but they do. How is it
possible?
Thank you.
Pavel Strnad

Including AAA at the top level, as in line 7, acts the same as including it
on Object, so every object suddenly has BBB available to it.

module A; class B; end; end
include A
Object::A
Fixnum::A
class X; end
X::A
X.ancestors # => [X, Object, A, Kernel, BasicObject]

···

On Wed, Feb 2, 2011 at 11:15 PM, Andrew Wagner <wagner.andrew@gmail.com>wrote:

This is really quite odd to me. Especially since AAA::BBB.constants returns
an empty array. Anybody have an answer to this?

On Wed, Feb 2, 2011 at 11:49 AM, Pavel Strnad <pavel.strnad@fel.cvut.cz > >wrote:

> Hi,
> I do not understand how is following code working:
> irb(main):001:0> module AAA
> irb(main):002:1> class BBB
> irb(main):003:2> end
> irb(main):004:1> end
> => nil
> irb(main):005:0> BBB::BBB
> NameError: uninitialized constant BBB
> from (irb):5
> from /usr/local/bin/irb:12:in `<main>'
> irb(main):006:0> AAA::BBB::BBB
> NameError: uninitialized constant AAA::BBB::BBB
> from (irb):6
> from /usr/local/bin/irb:12:in `<main>'
> irb(main):007:0> include AAA
> => Object
> irb(main):008:0> BBB::BBB
> => AAA::BBB
> irb(main):009:0> BBB::BBB::BBB
> => AAA::BBB
> irb(main):010:0> BBB::BBB::BBB::BBB
> => AAA::BBB
> irb(main):011:0> AAA::BBB::BBB::BBB

=> AAA::BBB
>
> I thought that last four lines will not work, but they do. How is it
> possible?
> Thank you.
> Pavel Strnad
>
>

Including AAA at the top level, as in line 7, acts the same as including it
on Object, so every object suddenly has BBB available to it.

This explanation makes sense, and certainly fits the facts. But why is doing
'include' from an irb prompt the same as including the module in Object? If
self points to main, and main is an instance of Object, shouldn't the module
get included into main's eigenclass?

I'm actually working on a static analysis tool that came up against the issue
of modeling Ruby's inclusion semantics recently. The top-level object has
a couple of special behaviors, designed to bring a few of the features of
classes to the top-level in a (hopefully) more intuitive way. If you run:

ruby -e 'p methods(false)'

You'll get:

[:to_s, :public, :private, :include]

to_s just returns "main", and public and private bring visibility to top-level code.
Include is defined (for 1.9.2) at vm.c:968:

static VALUE
top_include(int argc, VALUE *argv, VALUE self)
{
    rb_thread_t *th = GET_THREAD();

    rb_secure(4);
    if (th->top_wrapper) {
  rb_warning
      ("main#include in the wrapped load is effective only in wrapper module");
  return rb_mod_include(argc, argv, th->top_wrapper);
    }
    return rb_mod_include(argc, argv, rb_cObject);
}

The most important line being the most common one, the final one: it simply includes
the given modules into the Object class.

I haven't thought too hard about what the ramifications would be if it were instead
included into the main object's eigenclass, so this answer might not be too satisfying,
but well, there it is.

Cheers,
Mike Edgar
http://carboni.ca/

···

On Feb 2, 2011, at 11:01 PM, Andrew Wagner wrote:

Including AAA at the top level, as in line 7, acts the same as including it
on Object, so every object suddenly has BBB available to it.

This explanation makes sense, and certainly fits the facts. But why is doing
'include' from an irb prompt the same as including the module in Object? If
self points to main, and main is an instance of Object, shouldn't the module
get included into main's eigenclass?

Including AAA at the top level, as in line 7, acts the same as including it
on Object, so every object suddenly has BBB available to it.

This explanation makes sense, and certainly fits the facts. But why is doing
'include' from an irb prompt the same as including the module in Object? If
self points to main, and main is an instance of Object, shouldn't the module
get included into main's eigenclass?

I believe IRB mimics behavior of the Ruby interpreter here:

10:44:58 ~$ ruby19 <<CODE

module A; class B; end; end
include A
p B
p Fixnum::B
CODE

10:45:32 ~$ ruby19 -e 'p self'
main
10:45:51 ~$ irb19
Ruby version 1.9.2
irb(main):001:0> self
=> main

Reasoning behind this is certainly is that this way namespaces work as
expected. If only main would get access to the inclusion, you could
not use a constant nested in your included module in *any* other
class.

Personally I don't like including at top level that much because it
always includes the risk of name clashes. I usually do this only in
small or one off scripts.

Kind regards

robert

···

On Thu, Feb 3, 2011 at 5:01 AM, Andrew Wagner <wagner.andrew@gmail.com> wrote:
A::B
A::B

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/