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

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.

Interesting. Just to clarify: If my idea is worth anything it can't
really be implemented via a redefine-able operator. That would just change
the area of concern from #send being redefined to #operator being redefined.
I realize that Trans is basically just experimenting with syntax at this
point.

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).

Well, I would still argue that << would be better than >> for mnemonic
reasons but I understand that a lot more classes have << already defined.

3) It doesn't provide a "pervasive send" operator.

Well, as long as folks aren't redefining methods in BasicObject you *almost*
have a "pervasive send" operator:

   obj >> [BasicObject, :object_id]

I think there is a strong argument to be made that BasicObject should be
frozen. You can override methods there via inheritance but I don't think
BasicObject itself should be modified.

Gary Wright

···

On Jan 6, 2007, at 4:12 PM, Trans wrote:

Yeah, if we were to go the arrow route, you'd probably want

obj <- message and want <- to be something you can't override.

···

On 1/7/07, gwtmp01@mac.com <gwtmp01@mac.com> wrote:

On Jan 6, 2007, at 4:12 PM, Trans wrote:
> 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.

Interesting. Just to clarify: If my idea is worth anything it can't
really be implemented via a redefine-able operator. That would just
change
the area of concern from #send being redefined to #operator being
redefined.
I realize that Trans is basically just experimenting with syntax at this
point.

> 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).

Well, I would still argue that << would be better than >> for mnemonic
reasons but I understand that a lot more classes have << already
defined.