S
Stefan Rusterholz
Short primer: What are namespaces?
Matz talked (in 2005 I think) about a concept he named 'namespaces',
they would allow you to monkey patch e.g. Array in namespace :foo
without the patch being visible in namespace :bar, essentially to make
namespacing safe. He didn't implement it because it's too hard to.
I wonder why it is too hard, given that Class#clone exists and shadowing
constants within a module works fine. I wrote up a small proof of
concept which still has problems and could be extended further. It's
pure ruby, the problems should be solvable at C level.
The probably ugliest part is due to constant lookup rules in blocks, I
had to use string eval.
The code is nicely formatted viewable on http://pastie.caboo.se/131560
== Example code
require 'namespaces'
namespace :foo, %{
class Array
def bar
"bar"
end
end
p Array.new.bar
}
namespace :bar, %{
p Array.new.bar
}
== Example output
"bar"
testnamespaces.rb:xx:in `create': undefined method `bar' for []:Array
(NoMethodError)
from testnamespaces.rb:xx:in `namespace'
from testnamespaces.rb:xx
== namespaces.rb
module Kernel
def namespace(name, code)
Namespace.exist?(name) ? Namespace[name].module_eval(code) :
Namespace.create(name, code)
end
end
module Namespace
@space = {}
class <<self
def exist?(name)
@space.has_key?(name)
end
def [](name)
@space[name]
end
def create(name, code)
name = name.to_s.upcase
raise "Namespace '#{name}' exists already" if
@space.has_key?(name)
space = const_set(name, Module.new)
@space[name] = space
Object.constants.each { |c|
begin
@space[name].const_set(c, v.clone)
rescue; end
}
space.module_eval(code)
space
end
end
end
Problems that a pure ruby solution suffers and things that I didn't yet
add:
-Concurrency
-Literals
-Importing from other namespaces
-Recursively clone constants
-Blocks have lookup rules tied to definition context even with
module_eval, hence string evals
So now I wonder, am I missing something? Is the devil in the details, or
is one of the incomplete things in my proof of concept the show stopper?
I see that it would be some work, but I don't see how it would be hard.
Please enlighten me
Regards
Stefan
Matz talked (in 2005 I think) about a concept he named 'namespaces',
they would allow you to monkey patch e.g. Array in namespace :foo
without the patch being visible in namespace :bar, essentially to make
namespacing safe. He didn't implement it because it's too hard to.
I wonder why it is too hard, given that Class#clone exists and shadowing
constants within a module works fine. I wrote up a small proof of
concept which still has problems and could be extended further. It's
pure ruby, the problems should be solvable at C level.
The probably ugliest part is due to constant lookup rules in blocks, I
had to use string eval.
The code is nicely formatted viewable on http://pastie.caboo.se/131560
== Example code
require 'namespaces'
namespace :foo, %{
class Array
def bar
"bar"
end
end
p Array.new.bar
}
namespace :bar, %{
p Array.new.bar
}
== Example output
"bar"
testnamespaces.rb:xx:in `create': undefined method `bar' for []:Array
(NoMethodError)
from testnamespaces.rb:xx:in `namespace'
from testnamespaces.rb:xx
== namespaces.rb
module Kernel
def namespace(name, code)
Namespace.exist?(name) ? Namespace[name].module_eval(code) :
Namespace.create(name, code)
end
end
module Namespace
@space = {}
class <<self
def exist?(name)
@space.has_key?(name)
end
def [](name)
@space[name]
end
def create(name, code)
name = name.to_s.upcase
raise "Namespace '#{name}' exists already" if
@space.has_key?(name)
space = const_set(name, Module.new)
@space[name] = space
Object.constants.each { |c|
begin
@space[name].const_set(c, v.clone)
rescue; end
}
space.module_eval(code)
space
end
end
end
Problems that a pure ruby solution suffers and things that I didn't yet
add:
-Concurrency
-Literals
-Importing from other namespaces
-Recursively clone constants
-Blocks have lookup rules tied to definition context even with
module_eval, hence string evals
So now I wonder, am I missing something? Is the devil in the details, or
is one of the incomplete things in my proof of concept the show stopper?
I see that it would be some work, but I don't see how it would be hard.
Please enlighten me
Regards
Stefan