Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Method Namespace

Reply
Thread Tools

Method Namespace

 
 
Trans
Guest
Posts: n/a
 
      12-05-2006
I have need for a general purpose simple namespace construction. Not
selector namespaces, mind you, just a method namespace. I made the
following attempt. So close! But it fails b/c if a method is already
defined in the class and the namespace module being added also has a
method of the same name they will clash. I worked around it by aliasing
the method with a temporary name then realiasing it to the original
name. This words EXCEPT when super is called in the method (see the
test case a the bottom).

Anone have any better ways of implementing?

Thanks,
T.


# namespace.rb

require 'facet/functor'
require 'facet/module/basename'

class Module

# Define a simple namespace.
#
# class A
# attr_writer
# namespace :inside do
# def x; @x; end
# end
# end
#
# a = A.new
# a.x = 10
# a.inside.x #=> 10
# a.x # no method error

def namespace( mod, &blk )

# If block is given then create a module, othewise
# get the name of the module.
if block_given?
name = mod.to_s
mod = Module.new(&blk)
else
name = mod.basename.downcase
mod = mod.dup
end

# We have to work around name clashes.
nameclashes = mod.instance_methods & instance_methods
nameclashes.each do |n|
alias_method "#{n}:namespace", n
end

# Include the module. This is neccessary, otherwise
# Ruby won't let us bind the instance methods.
include mod

# Undefine the instance methods of the module.
mod.instance_methods.each{ |m| undef_method m }

# Redefine the methods that clashed.
nameclashes.each do |n|
alias_method n, "#{n}:namespace"
undef_method "#{n}:namespace"
end

# Add a method for the namespace that delegates
# via the Functor to the module instance methods.
define_method(name) do
Functor.new(mod) do |op, base, *args|
base.instance_method(op).bind(self).call(*args)
end
end
end

end


# begin test

require 'test/unit'

class TestNamespace1 < Test::Unit::TestCase

module M
def x; "x"; end
end

class C
namespace M
end

def test_01
c = C.new
assert_equal('x', c.m.x)
end

def test_02
c = C.new
assert_raises(NoMethodError){ c.x }
end

end


class TestNamespace2 < Test::Unit::TestCase

class B
def x; 1; end
end

class C < B
def x; super; end
namespace :m do
def x; "x"; end
end
end

def test_01
c = C.new
assert_equal('x', c.m.x)
end

# THIS FAILS !!!
def test_02
c = C.new
assert_equal(1, c.x)
end

end


 
Reply With Quote
 
 
 
 
Pit Capitain
Guest
Posts: n/a
 
      12-05-2006
Trans schrieb:
> I have need for a general purpose simple namespace construction.
> ...
> This words EXCEPT when super is called in the method (see the
> test case a the bottom).
> ...


Tom, could you try this version?

def namespace( mod, &blk )

# If block is given then create a module, otherwise
# get the name of the module.
if block_given?
name = mod.to_s
mod = Module.new(&blk)
else
name = mod.basename.downcase
mod = mod.dup
end

# Include the module. This is neccessary, otherwise
# Ruby won't let us bind the instance methods.
include mod

# Save the instance methods of the module and
# replace them with a "transparent" version.
methods = {}
mod.instance_methods(false).each do |m|
methods[ m.to_sym ] = mod.instance_method(m)
mod.instance_eval do
define_method(m) do
super
end
end
end

# Add a method for the namespace that delegates
# via the Functor to the saved instance methods.
define_method(name) do
Functor.new(methods) do |op, mtab, *args|
mtab[op].bind(self).call(*args)
end
end
end

Regards,
Pit

 
Reply With Quote
 
 
 
 
Trans
Guest
Posts: n/a
 
      12-06-2006

Pit Capitain wrote:
> Tom, could you try this version?
>
> def namespace( mod, &blk )
>
> # If block is given then create a module, otherwise
> # get the name of the module.
> if block_given?
> name = mod.to_s
> mod = Module.new(&blk)
> else
> name = mod.basename.downcase
> mod = mod.dup
> end
>
> # Include the module. This is neccessary, otherwise
> # Ruby won't let us bind the instance methods.
> include mod
>
> # Save the instance methods of the module and
> # replace them with a "transparent" version.
> methods = {}
> mod.instance_methods(false).each do |m|
> methods[ m.to_sym ] = mod.instance_method(m)
> mod.instance_eval do
> define_method(m) do
> super
> end
> end
> end
>
> # Add a method for the namespace that delegates
> # via the Functor to the saved instance methods.
> define_method(name) do
> Functor.new(methods) do |op, mtab, *args|
> mtab[op].bind(self).call(*args)
> end
> end
> end


Bloody hek, that's a clever solution. Works like a charm. Pit Captain,
you never cease to amaze! I'm putting this in Facets to replace the
weak SimpleDelegtor I had been using.

Thanks!
T.


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ERROR CS0234: The type or namespace name 'DataAccessHelper' does not exist in the namespace 'BCC' (are you missing an assembly reference?) li.eddie@gmail.com ASP .Net 0 01-06-2006 11:31 AM
[XML Schema] Including a schema document with absent target namespace to a schema with specified target namespace Stanimir Stamenkov XML 3 04-25-2005 09:59 AM
Reaching into the default namespace when using another namespace. Jason Heyes C++ 1 11-19-2004 02:36 AM
Namespace: Is it a scope or a namespace? Anonymous C++ 3 08-18-2003 01:31 PM
Help:Why can't I use namespace System.Web? It is said that this namespace doesn't exist. But it should exist. ASP .Net 1 07-29-2003 04:31 PM



Advertisments