"cyclic include" error inside anonymous module

(Brian Candler) #1

Like I've said previously, I prefer ruby and C :slight_smile:

moulon% cat b.rb
#!/usr/bin/ruby
module Anonymous
   module M
      include Anonymous
      extend Anonymous
   end

   include M
end

moulon%

moulon% ./b.rb
./b.rb:8:in `append_features': cyclic include detected (ArgumentError)
  from ./b.rb:8

OK, thank you.

So next question: why, when I define module M inside an anonymous module,
does Ruby make module M both include and extend the enclosing module?

Looking at ri documentation:

(1) Module#include "Invokes +Module.append_features+ on each parameter in
turn."

Module#append_features says: "Ruby's default implementation is to add the
     constants, methods, and module variables of this module to _mod_ if
     this module has not already been added to _mod_ or one of its
     ancestors."

[I *think* this means that this module is added to _mod_'s ancestors]

(2) Object#extend "Adds to _obj_ the instance methods from each module given
as a parameter."

So, presumably these don't do anything useful unless the anonymous module
has any constants, methods or instance methods, or module variables of its
own.

And even if it had some: I thought that when searching for (say) constant
Foo, Ruby looks first inside the current namespace and then the enclosing
namespaces anyway? So why explicitly include the enclosing namespace?

Hmm. I wonder if this demonstrates the problem?

    #module Anon
    Module.new.instance_eval do
       Foo = 6

       module M
          Bar = 7
          p Foo, Bar
       end
       p Foo

       include M
       p Bar # FAILS HERE
    end

This program fails where shown, but works if the first line is uncommented
and the second comment out.

However, the "include/extend" trick you showed doesn't help here:

    Module.new.instance_eval do
       Anon = self
       Foo = 6

       module M
          Bar = 7
          p Foo, Bar
          include Anon
          extend Anon
       end
       p Foo

       include M
       p Bar
    end

This gives the same 'cyclic include' error which started the thread.

Perhaps you can give an example of where the automatic include/extend inside
an anonymous module is necessary or useful?

Regards,

Brian.

(ts) #2

So next question: why, when I define module M inside an anonymous module,
does Ruby make module M both include and extend the enclosing module?

load("file", true) is a security mechanism but, unlike $SAFE = 4, use it
only with file that you can trust because it's easy to bypass it.

Guy Decoux