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