Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Re-opened nested module anomaly in Ruby

Why does re-opening a nested module give different results depending on the syntax used? For example, this works fine:

module A
  module E
  end
end
module A
  module E
    def E.e
    end
  end
end

But this:

module A
  module E
  end
end
module A::E
  def E.e
  end
end

gives the error:

reopen.rb:6:in `<module:E>': uninitialized constant A::E::E (NameError)
from reopen.rb:5:in `<main>'

(Before someone points this out, a workaround is to use self instead of the module name when defining E.e, but that's not really the point of this post.)

like image 260
glyn Avatar asked Jul 11 '13 09:07

glyn


1 Answers

The module keyword sets a namespace context that is checked for references to existing names of Modules. These namespaces are then searched inner-to-outer to resolve references to Module (and Class) names.

In your first example, it looks like you may need to define E.e inside module E block, but in fact you don't:

module A
  module E
  end
end
module A
  def E.e
  end
end

What happens in both your examples is that Ruby looks at the current namespace, and tries <namespace>::E as a module name. So in both examples, the first thing it checks is in fact A::E::E which does not exist. Then it falls back to the next context. Which is where the examples differ: In the first example it is A::E which is valid, in the second example, it is just E which is not. The error that it then throws relates to the first name it checked.

like image 76
Neil Slater Avatar answered Sep 29 '22 02:09

Neil Slater