From: intc_ctor@... (Phil Tomson) Date: 2004-01-23T05:35:02+09:00 Subject: Re: Debunking misconceptions about Ruby Mauricio Fern�ndez wrote in message news:<20040122095123.GA18582@student.ei.uni-stuttgart.de>... > On Thu, Jan 22, 2004 at 10:04:51AM +0900, Gavin Sinclair wrote: > > > > That is a feature I would definitely like to see in Ruby ('include' > > having an effect local to the enclosing block, or whatever the > > Would the 'new include' work like the current one, i.e. using a proxy class > (so that the return value of Module#ancestors changes), or are you rather > thinking of a way to use singleton methods from another module/object? > > That is, is the feature you're thinking of only related to the namespace > in a scope or does it involve something more complex such as several > per-object namespaces? > > > terminology should be). Must remember to raise an RCR. > > batsman@tux-chan:/tmp$ expand -t2 c.rb > require 'test/unit' > > # scoped singleton method import > # > # using(ModWithSingletons, someobject) do > # blah # runs ModWithSingletons.blah or someobject.blah if it cannot be > # # resolved with self > # end > # > # can be nested but is not thread-safe > def using(*modules) > ## this doesn't propagate the block :-( > #klass = class << self; self end > #klass.module_eval{ alias_method :_method_missing_, :method_missing } > #klass.send(:define_method,:method_missing) do |meth,*args| > # begin > # _method_missing_ meth, *args > # rescue NameError > # modules.each do |m| > # return m.send(meth, *args) if m.respond_to? meth > # end > # raise > # end > #end > @_using_modules_ ||= [] > @_level_ ||= 0 > @_level_ += 1 > old = @_using_modules_ > @_using_modules_ = modules + @_using_modules_ > if @_level_ == 1 > class << self > alias_method :_method_missing_, :method_missing > def method_missing(meth, *args, &block) > begin > _method_missing_ meth, *args, &block > rescue NameError > @_using_modules_.each do |m| > return m.send(meth, *args, &block) if m.respond_to? meth > end > raise > end > end > end > end > begin > yield > ensure > @_level_ -= 1 > if @_level_ == 0 > class << self > alias_method :method_missing, :_method_missing_ > end > end > @_using_modules_ = old > end > end > > > class TC_using < Test::Unit::TestCase > > module Blah; def self.foo; "Blah.foo" end end > module Foo; def self.foo; "Foo.foo" end end > module Bar > def self.bar; "Bar.bar" end > def self.baz; yield end > end > > def test_single_module > assert_equal("Foo.foo", using(Foo){ foo }) > assert_equal("Blah.foo", using(Blah){ foo }) > end > > def test_several_modules > assert_equal("Foo.foo", using(Foo,Blah){foo}) > assert_equal("Blah.foo", using(Blah,Foo){foo}) > end > > def test_call_with_block > assert_equal("Bar.baz", using(Bar){baz{"Bar.baz"}}) > end > > def test_nested > assert_equal("Blah.foo", using(Foo){using(Blah){foo}}) > using(Foo) do > assert_equal("Blah.foo", using(Blah){foo}) > assert_equal("Foo.foo", foo) > end > end > > def test_namerror > assert_raises(NameError) { using(Foo){ jurl } } > end > end > > batsman@tux-chan:/tmp$ ruby c.rb > Loaded suite c > Started > .... > Finished in 0.003045 seconds. > > 5 tests, 9 assertions, 0 failures, 0 errors > Cool. A good example of how just about any new feature that someone thinks of can often be implemented in Ruby without requiring a change to the language itself. Oh, and I also thought it was about time to change the subject name on this thread: I don't think Ruby has 'bad fame' (as in "The Infamous Ruby"). I find that those who have heard of Ruby usually have heard good things about it and if they have heard negatives those perceptions are often out of date. Phil