From: Trans Date: 2007-01-07T06:12:37+09:00 Subject: send operator: proof of concept implementation Put together a proof of concept of Gary Wright's idea of using an operator for send instead of a method. This also incorporates an implementation of Ara's Pervasives. There are a couple caveats to this implementation however that would have to be handled in any production version. 1) It uses >> rather then ->, for obvious reasons. So as it is, it will not work with a few classes that already use >> (unless they are redefined). 2) You have to pass an array, since an operator normally can't handle more that one arg. This also means unfortunately that blocks can't be passed. 3) It doesn't provide a "pervasive send" operator. Usage: # send equivalent to '.' obj >> [:method, *args] # send as (binds to method in parent class/module) obj >> [Ancestor, :method, *args] The second form can also be used to bypass privacy. obj >> [(obj>>:class), :method, *args] Albeit this will bypass singletons (aside from this it would be nice to have method that returns the singleton if it exists, but the regular class otherwise). --- module Kernel module Pervasives METHODS = {} Kernel.instance_methods.each do |m| METHODS[m] = Kernel.instance_method(m) end METHODS.each do |s,m| define_method s do |o,*a| m.bind(o).call(*a) end module_function s end end Pervasives.freeze(Pervasives) def >>(a) a = [a].flatten case a[0] when Module, Class c, m, *a = *a c.instance_method(m).bind(self).call(*a) else if respond_to?(a[0]) Pervasives.send(self,*a) elsif respond_to?(:method_missing) method_missing(*a) else raise NoMethodError, "private method called for #{self}" end end end end #=begin test require 'test/unit' class TestSendOP < Test::Unit::TestCase class C def a; "c"; end end class X < C def send; "send"; end def a; "a"; end private def b; "b"; end end def setup @x = X.new end def test_send assert_equal( "send", @x.send ) end def test_normal assert_equal( "a", @x >> [:a] ) end def test_as_C assert_equal( "c", @x >> [C,:a] ) end def test_singleton assert_equal( "a", @x >> [(class<<@x;self;end),:a] ) end def test_singleton_bypass_private assert_equal( "b", @x >> [(class<<@x;self;end),:b] ) end def test_private assert_raises(NoMethodError){ @x >> [:b] } end end #=end