Namespaces, inverted

Apologies if this topic has already been beaten to death.
Oh, and for the long-windedness.

Using modules for namespaces is somewhat unwieldy. I'd call it one
of the few evil parts of Ruby, although its implementation is
understandable when viewed from an OO standpoint. It's just
tiresome to A) invent and B) use unique namespaces in Ruby (and
by 'unique' I mean FooSoft Inc. wrapping all their libraries inside a
module FooSoft).

Of the current commercial languages, the package system of Java is
likely to be the best for flexibility and uniqueness, although it
does suffer from verbosity--and I wouldn't mind seeing Haskell-style
limited export capabilities, either. This, of course, should be
possible to do in Ruby 'on top' of the current system.

But why use unique namespaces? Modules are certainly useful for
partitioning a project into its constituent parts, but unique
namespaces are only useful in the context of that code being used
by another party where it can prevent namespace clashes. This, of
course, is highly site-dependent: it may not be necessary at all,
they may already have a package with the same 'unique' namespace,
they may not like the module name, etc. etc.

Why not have the 'client' decide if and which namespace to assign
to a foreign library? As in, if I want to use FooBar Inc.'s Math
package, they need not wrap it in module FooBar, but can just ship
it as Math. Then I just wrap it to Extern, my namespace for all
third-party modules. In current Ruby, I suppose this can be achieved
with something like (please correct if I'm wrong, this is off the top
of my head):

···

-----

# Toplevel
# This is just an aesthetically pleasing (?) implementation,
# I'm not sure about using String for the ascribed purpose.

def import file
file[:module].module_eval(IO.readlines(file[:name]).join)
end

class String
def as module
  {:name => self, :module => module}
end

# Convenience
alias :in :as
alias :into :as
end

# Usage
import "foomath.rb".as Extern

rand = Extern::Math.random()

-----
Or is that just counterintuitive? It would at least conceptually
free the module construct from doing double duty as the namespace
construct.

The Ruby implementation is obviously somewhat slow but it could be
written to use the same routines as require()/load() with the
exception of doing the loading in the context of a given module. I
think the above 'implementation' also handles altogether non-moduled
files but I may be wrong in my it's-Sunday-morning-and-I'm-at-work
stupor.

E

I like the idea very much, but there are some difficulties...

def import file
  file[:module].module_eval(IO.readlines(file[:name]).join)
end

class String
  def as mod
   {:name => self, :module => mod}
  end
end

module Extern; end
# It's a little awkward, but you gotta do this first, if
# you want to refer to the module as below.

libfile = "/usr/local/lib/ruby/1.8/complex.rb"
# One problem is the cumbersome path name to the library file.

import libfile.as(Extern)
# This fails because the library complex.rb tries to open an existing
# class, Numeric, and modify its contents. But instead it opens a new
# module, also called Numeric, that lives inside the wrapper. You can
# fix this in complex.rb (assuming you want to touch 3rd party code)
# by referring to the module as ::Numeric when you define it. But
# there's still a problem...

z = Extern::Complex(1,2)
# "undefined method `Complex' for Extern::Complex"
# This is due to the special effect of "def foo" at the top level in
# ruby--it defines an instance method of Object. But the effect within
# the wrapper module is very different. Again it's possible to modify
# the 3rd party code, as follows:

···

eero.saynatkari@kolumbus.fi wrote:

Apologies if this topic has already been beaten to death.
Oh, and for the long-windedness.

Using modules for namespaces is somewhat unwieldy. I'd call it one of the few evil parts of Ruby, although its implementation is
understandable when viewed from an OO standpoint. It's just
tiresome to A) invent and B) use unique namespaces in Ruby (and
by 'unique' I mean FooSoft Inc. wrapping all their libraries inside a
module FooSoft).

Of the current commercial languages, the package system of Java is
likely to be the best for flexibility and uniqueness, although it
does suffer from verbosity--and I wouldn't mind seeing Haskell-style
limited export capabilities, either. This, of course, should be
possible to do in Ruby 'on top' of the current system.

But why use unique namespaces? Modules are certainly useful for partitioning a project into its constituent parts, but unique namespaces are only useful in the context of that code being used
by another party where it can prevent namespace clashes. This, of course, is highly site-dependent: it may not be necessary at all, they may already have a package with the same 'unique' namespace,
they may not like the module name, etc. etc.

Why not have the 'client' decide if and which namespace to assign
to a foreign library? As in, if I want to use FooBar Inc.'s Math
package, they need not wrap it in module FooBar, but can just ship
it as Math. Then I just wrap it to Extern, my namespace for all
third-party modules. In current Ruby, I suppose this can be achieved
with something like (please correct if I'm wrong, this is off the top of my head):
-----

# Toplevel
# This is just an aesthetically pleasing (?) implementation,
# I'm not sure about using String for the ascribed purpose.

def import file
file[:module].module_eval(IO.readlines(file[:name]).join)
end

class String
def as module
  {:name => self, :module => module}
end

# Convenience
alias :in :as
alias :into :as
end

# Usage
import "foomath.rb".as Extern

rand = Extern::Math.random()

-----
Or is that just counterintuitive? It would at least conceptually
free the module construct from doing double duty as the namespace
construct.

The Ruby implementation is obviously somewhat slow but it could be written to use the same routines as require()/load() with the exception of doing the loading in the context of a given module. I think the above 'implementation' also handles altogether non-moduled files but I may be wrong in my it's-Sunday-morning-and-I'm-at-work stupor.

#
# class ::Object
# def Complex(a, b = 0)
# # ...
# end
# end

"Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> schrieb im Newsbeitrag news:41D0E5EF.1040308@path.berkeley.edu...

Apologies if this topic has already been beaten to death.
Oh, and for the long-windedness.

Using modules for namespaces is somewhat unwieldy. I'd call it one of the few evil parts of Ruby, although its implementation is
understandable when viewed from an OO standpoint. It's just
tiresome to A) invent and B) use unique namespaces in Ruby (and
by 'unique' I mean FooSoft Inc. wrapping all their libraries inside a
module FooSoft).

Of the current commercial languages, the package system of Java is
likely to be the best for flexibility and uniqueness, although it
does suffer from verbosity--and I wouldn't mind seeing Haskell-style
limited export capabilities, either. This, of course, should be
possible to do in Ruby 'on top' of the current system. But why use unique namespaces? Modules are certainly useful for partitioning a project into its constituent parts, but unique namespaces are only useful in the context of that code being used
by another party where it can prevent namespace clashes. This, of course, is highly site-dependent: it may not be necessary at all, they may already have a package with the same 'unique' namespace,
they may not like the module name, etc. etc.

Why not have the 'client' decide if and which namespace to assign
to a foreign library? As in, if I want to use FooBar Inc.'s Math
package, they need not wrap it in module FooBar, but can just ship
it as Math. Then I just wrap it to Extern, my namespace for all
third-party modules. In current Ruby, I suppose this can be achieved
with something like (please correct if I'm wrong, this is off the top of my head):
-----

# Toplevel
# This is just an aesthetically pleasing (?) implementation,
# I'm not sure about using String for the ascribed purpose.

def import file
file[:module].module_eval(IO.readlines(file[:name]).join)
end

class String
def as module
  {:name => self, :module => module}
end

# Convenience
alias :in :as
alias :into :as
end

# Usage
import "foomath.rb".as Extern

rand = Extern::Math.random()

-----
Or is that just counterintuitive? It would at least conceptually
free the module construct from doing double duty as the namespace
construct.

The Ruby implementation is obviously somewhat slow but it could be written to use the same routines as require()/load() with the exception of doing the loading in the context of a given module. I think the above 'implementation' also handles altogether non-moduled files but I may be wrong in my it's-Sunday-morning-and-I'm-at-work stupor.

I like the idea very much, but there are some difficulties...

def import file
file[:module].module_eval(IO.readlines(file[:name]).join)
end

class String
def as mod
  {:name => self, :module => mod}
end
end

module Extern; end
# It's a little awkward, but you gotta do this first, if
# you want to refer to the module as below.

libfile = "/usr/local/lib/ruby/1.8/complex.rb"
# One problem is the cumbersome path name to the library file.

import libfile.as(Extern)
# This fails because the library complex.rb tries to open an existing
# class, Numeric, and modify its contents. But instead it opens a new
# module, also called Numeric, that lives inside the wrapper. You can
# fix this in complex.rb (assuming you want to touch 3rd party code)
# by referring to the module as ::Numeric when you define it. But
# there's still a problem...

z = Extern::Complex(1,2)
# "undefined method `Complex' for Extern::Complex"
# This is due to the special effect of "def foo" at the top level in
# ruby--it defines an instance method of Object. But the effect within
# the wrapper module is very different. Again it's possible to modify
# the 3rd party code, as follows:
#
# class ::Object
# def Complex(a, b = 0)
# # ...
# end
# end

I don't like the idea of the as method as it cannot be used reasonable in other circumstances as module loading. The code really does not belong into class String IMHO.

We have Kernel#load [1] with a similar functionality already. Currently it accepts an additional parameter to enforce wrapping of the file in an anonymous module. That could be extended to accept a module as well; that then would be the module used. Then we can do

load "foo.rb" # not wrapped
load "foo.rb" # wrapped in an anonymous module
load "foo.rb", MyExternal # wrapped in MyExternal

Additionally / Alternatively it could be useful to have a per module require like this:

class Module
  def require(*files)
    # puts "loading in module #{self}: #{files.inspect}"
    @loaded ||= {}
    files.each do |f|
      unless @loaded[f]
        # real load code that wraps contents of f in self
        @loaded[f] = true
      end
    end
  end
end

Then we could do

module Foo
  require "bar"
end

and even if we do the same later again, "bar" is only loaded once (see [2]).

Sounds like an RCR candidate, doesn't it?

Kind regards

    robert

[1] module Kernel - RDoc Documentation

[2] http://www.ruby-doc.org/core/classes/Kernel.html#M001745

···

eero.saynatkari@kolumbus.fi wrote:

Robert Klemme wrote:
...

We have Kernel#load [1] with a similar functionality already. Currently it accepts an additional parameter to enforce wrapping of the file in an anonymous module. That could be extended to accept a module as well; that then would be the module used. Then we can do

load "foo.rb" # not wrapped
load "foo.rb" # wrapped in an anonymous module
load "foo.rb", MyExternal # wrapped in MyExternal

Wrapping is a nice idea (see raa:script for one approach), but the wrapped lib will break if it depends on modifying classes or modules in the global scope or defining global methods (the Complex example in my previous email).

There is the idea the OP mentioned of parsing input files and rewriting them to be explicit about the scope of definitions, automating the kludgy hack I proposed for complex.rb. But that will break if the lib uses dynamic code generation.

Maybe library writers should follow a standard of making their code explicit about namespaces:

1. If you open and existing class, give an absolute path to it:

   class ::Integer

rather than

   class Integer

2. Global methods defs should be wrapped like this:

   class ::Object
     def global_meth ... end
   end

3. References to constants (not just classes and modules) defined in the lib should be relative:

   class Foo
   end

   f = Foo.new

and not absolute:

   f = ::Foo.new

(although I can't imagine that many libs have this problem).

4. Anything else to protect the lib from breakage when wrapping?

"Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> schrieb im Newsbeitrag news:41D1D875.8020501@path.berkeley.edu...

Robert Klemme wrote:
..

We have Kernel#load [1] with a similar functionality already. Currently it accepts an additional parameter to enforce wrapping of the file in an anonymous module. That could be extended to accept a module as well; that then would be the module used. Then we can do

load "foo.rb" # not wrapped
load "foo.rb" # wrapped in an anonymous module
load "foo.rb", MyExternal # wrapped in MyExternal

Wrapping is a nice idea (see raa:script for one approach), but the wrapped lib will break if it depends on modifying classes or modules in the global scope or defining global methods (the Complex example in my previous email).

There is the idea the OP mentioned of parsing input files and rewriting them to be explicit about the scope of definitions, automating the kludgy hack I proposed for complex.rb. But that will break if the lib uses dynamic code generation.

Maybe library writers should follow a standard of making their code explicit about namespaces:

1. If you open and existing class, give an absolute path to it:

  class ::Integer

rather than

  class Integer

Totally agree. I guess this is seldom used these days.

2. Global methods defs should be wrapped like this:

  class ::Object
    def global_meth ... end
  end

That's really the same as case 1, isn't it?

3. References to constants (not just classes and modules) defined in the lib should be relative:

  class Foo
  end

  f = Foo.new

and not absolute:

  f = ::Foo.new

(although I can't imagine that many libs have this problem).

I think so, too.

4. Anything else to protect the lib from breakage when wrapping?

We would have to think about what happens if a wrapped module requires another module. If that other module is a standard module you'll certainly do not want it to be included in the wrapping namespace. If it belongs to the same lib, then of course you want it wrapped. So the crucial question is: how are these require's distinguished? I'm not 100% sure but I think a simple 'require "foo"' will look relative as well as in global directories - that might be a chance to distinguish...

As much as I like the original idea of wrapping classes in namespaces (much the way that can be done with C++ because of #include) I believe this needs more thought.

Kind regards

    robert