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.

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