From: Eric Mahurin Date: 2005-08-31T02:03:55+09:00 Subject: Re: Method behaves differently when called using #send --- Peter Vanbroekhoven wrote: > On Wed, 31 Aug 2005, Peter Vanbroekhoven wrote: > > > On Tue, 30 Aug 2005, David A. Black wrote: > > > >> I see what you mean; it's very magic. I can't think of a > way to > >> implement it in Ruby, and even though someone will be able > to with dl > >> or whatever, it will still be too magic :-) > > > > Actually... Here's an implementation using the very thing > that started this > > thread: > > > > class Object > > private :send > > def method_missing(m, *args, &blk) > > if m == :send > > eval "self.#{args[0]}(*args[1..-1], &blk)" > > else > > eval "#{m}(*args, &blk)" > > end > > end > > end > > > > class A > > def do_sth > > puts "hello" > > end > > private :do_sth > > end > > > > A.new.instance_eval { do_sth } # => prints "hello" > > A.new.do_sth # => raises NoMethodError > > OK, pasted the wrong version... Here goes another try: > > class Object > private :send > def method_missing(m, *args, &blk) > if m == :send > eval "self.#{args[0]}(*args[1..-1], &blk)" > else > super > end > end > end > > class A > def do_sth > puts "hello" > end > private :do_sth > end > > A.new.instance_eval { send(:do_sth) } # => prints "hello" > A.new.send(:do_sth) # => raises NoMethodError > > Peter How about a version that allow classes to override send and call the original with super? Or how about aliasing send? Here are some of the tests I showed in a previous message with this: a = A.new a.send(:do_sth) # => raises NoMethodError a.send(:send,:do_sth) # => raises NoMethodError a.instance_eval{send(...)} # => prints "hello" a.instance_eval{send(:send,...)} # => prints "hello" class A alias _send send def send(m,*args,&block) super end end a.send(:do_sth) # => prints "hello" a.instance_eval{send(:do_sth)} # => prints "hello" a._send(:do_sth) # => prints "hello" a.instance_eval{_send(:do_sth)} # => prints "hello" Notice you lose the dual functionality as soon as you do anything to send. It looks like you can get it back by doing this: class A private :_send private :send end It is quite difficult to follow what is going on in the above examples and why it works. This is an interesting way of determining whether a method was called with or without a receiver. But, I still think it isn't a good idea. I think a method's functionality should be independent of that. __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com