Forum: Ruby-core [ruby-trunk - Feature #7748][Open] Contextual send

Posted by Thomas Sawyer (7rans)
on 2013-01-28 08:11
(Received via mailing list)
Issue #7748 has been reported by trans (Thomas Sawyer).

----------------------------------------
Feature #7748: Contextual send
https://bugs.ruby-lang.org/issues/7748

Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: Next Major


=begin
If I write a method that uses #send vs. #public_send, I am making an 
assumption about how that method is invoked. For example, take the 
simplest form of such a method:

  class String
    def send_out(op, *a, &b)
      send(op, *a, &b)
    end
  end

This code has a bug in it, in the sense that it can be used to call 
private string methods. The solution is to use #public_send. In most 
cases that will be fine. But if anyone tries to reuse the method while 
extending String themselves, e.g.

  class String
    def send_out(op, *a, &b)
      public_send(op, *a, &b)
    end

    def some_public_method
      send_out(:some_private_method)
    end

    private
    def some_private_method
    end
  end

Then it will be a problem b/c it cannot be used on a private supporting 
method.

So it seems like there should be something like a ((*contextual send*)) 
which invokes a send with the same visibility as the parent method is 
invoked. e.g.

  class String
    def send_out(op, *a, &b)
      contextual_send(op, *a, &b)
    end
  end

And then all cases will work as expected.
=end
Posted by Nobuyoshi Nakada (nobu)
on 2013-02-03 05:34
(Received via mailing list)
Issue #7748 has been updated by nobu (Nobuyoshi Nakada).


#send had been implemented in that manner once, but reverted and 
#public_send was separated instead.
----------------------------------------
Feature #7748: Contextual send
https://bugs.ruby-lang.org/issues/7748#change-35793

Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: Next Major


=begin
If I write a method that uses #send vs. #public_send, I am making an 
assumption about how that method is invoked. For example, take the 
simplest form of such a method:

  class String
    def send_out(op, *a, &b)
      send(op, *a, &b)
    end
  end

This code has a bug in it, in the sense that it can be used to call 
private string methods. The solution is to use #public_send. In most 
cases that will be fine. But if anyone tries to reuse the method while 
extending String themselves, e.g.

  class String
    def send_out(op, *a, &b)
      public_send(op, *a, &b)
    end

    def some_public_method
      send_out(:some_private_method)
    end

    private
    def some_private_method
    end
  end

Then it will be a problem b/c it cannot be used on a private supporting 
method.

So it seems like there should be something like a ((*contextual send*)) 
which invokes a send with the same visibility as the parent method is 
invoked. e.g.

  class String
    def send_out(op, *a, &b)
      contextual_send(op, *a, &b)
    end
  end

And then all cases will work as expected.
=end
Posted by Thomas Sawyer (7rans)
on 2013-02-03 09:38
(Received via mailing list)
Issue #7748 has been updated by trans (Thomas Sawyer).


Ah, so this has been thought of before. I agree it should not replace 
behaviour of private #send (although, how much sweeter the syntax if it 
were called #private_send ?). But as an additional method, it would be 
useful. -- Or was there some reason, other than zonking #send, that made 
it "bad"?

----------------------------------------
Feature #7748: Contextual send
https://bugs.ruby-lang.org/issues/7748#change-35799

Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: Next Major


=begin
If I write a method that uses #send vs. #public_send, I am making an 
assumption about how that method is invoked. For example, take the 
simplest form of such a method:

  class String
    def send_out(op, *a, &b)
      send(op, *a, &b)
    end
  end

This code has a bug in it, in the sense that it can be used to call 
private string methods. The solution is to use #public_send. In most 
cases that will be fine. But if anyone tries to reuse the method while 
extending String themselves, e.g.

  class String
    def send_out(op, *a, &b)
      public_send(op, *a, &b)
    end

    def some_public_method
      send_out(:some_private_method)
    end

    private
    def some_private_method
    end
  end

Then it will be a problem b/c it cannot be used on a private supporting 
method.

So it seems like there should be something like a ((*contextual send*)) 
which invokes a send with the same visibility as the parent method is 
invoked. e.g.

  class String
    def send_out(op, *a, &b)
      contextual_send(op, *a, &b)
    end
  end

And then all cases will work as expected.
=end
Posted by ko1 (Koichi Sasada) (Guest)
on 2013-02-22 01:10
(Received via mailing list)
Issue #7748 has been updated by ko1 (Koichi Sasada).

Assignee set to matz (Yukihiro Matsumoto)

I think matz tried it.
Matz: Could you give us your knowledge?

----------------------------------------
Feature #7748: Contextual send
https://bugs.ruby-lang.org/issues/7748#change-36740

Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


=begin
If I write a method that uses #send vs. #public_send, I am making an 
assumption about how that method is invoked. For example, take the 
simplest form of such a method:

  class String
    def send_out(op, *a, &b)
      send(op, *a, &b)
    end
  end

This code has a bug in it, in the sense that it can be used to call 
private string methods. The solution is to use #public_send. In most 
cases that will be fine. But if anyone tries to reuse the method while 
extending String themselves, e.g.

  class String
    def send_out(op, *a, &b)
      public_send(op, *a, &b)
    end

    def some_public_method
      send_out(:some_private_method)
    end

    private
    def some_private_method
    end
  end

Then it will be a problem b/c it cannot be used on a private supporting 
method.

So it seems like there should be something like a ((*contextual send*)) 
which invokes a send with the same visibility as the parent method is 
invoked. e.g.

  class String
    def send_out(op, *a, &b)
      contextual_send(op, *a, &b)
    end
  end

And then all cases will work as expected.
=end
Posted by matz (Yukihiro Matsumoto) (Guest)
on 2013-02-22 01:19
(Received via mailing list)
Issue #7748 has been updated by matz (Yukihiro Matsumoto).


=begin
What I did was allowing ((%send%)) to invoke public method when called 
without explicit receiver.

And I gave up the idea because (a) it made send behavior more complex, 
(b) it slightly slowed down #send, (c) it was difficult to implement it 
in other implementations.

Matz.
=end

----------------------------------------
Feature #7748: Contextual send
https://bugs.ruby-lang.org/issues/7748#change-36745

Author: trans (Thomas Sawyer)
Status: Open
Priority: Normal
Assignee: matz (Yukihiro Matsumoto)
Category: core
Target version: Next Major


=begin
If I write a method that uses #send vs. #public_send, I am making an 
assumption about how that method is invoked. For example, take the 
simplest form of such a method:

  class String
    def send_out(op, *a, &b)
      send(op, *a, &b)
    end
  end

This code has a bug in it, in the sense that it can be used to call 
private string methods. The solution is to use #public_send. In most 
cases that will be fine. But if anyone tries to reuse the method while 
extending String themselves, e.g.

  class String
    def send_out(op, *a, &b)
      public_send(op, *a, &b)
    end

    def some_public_method
      send_out(:some_private_method)
    end

    private
    def some_private_method
    end
  end

Then it will be a problem b/c it cannot be used on a private supporting 
method.

So it seems like there should be something like a ((*contextual send*)) 
which invokes a send with the same visibility as the parent method is 
invoked. e.g.

  class String
    def send_out(op, *a, &b)
      contextual_send(op, *a, &b)
    end
  end

And then all cases will work as expected.
=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.