Issue #15428 has been updated by nobu (Nobuyoshi Nakada).


> > `#to_proc` is not an implicit conversion method, as it needs the specific syntax, `&`.
> 
> But ideologically, it is the way to designate "this object quacks as a `Proc`", e.g. could be used instead of a `Proc` object.

The point is that is done *explicitly*.

> > It is a usual case that a method may expect its argument to have particular method(s),
> > e.g., `String#+` expects `#to_str` on non-string argument.
> 
> Well, I believe that `#to_str` is an argument towards _my_ point :)

No, `#to_proc` is not similar to `#to_str`, but `#to_s`.

> Currently, we have (not, in fact, very well-documented, but still existing) convention, that some methods are used for coercion of other objects to compatible class. Typically, they are discussed in class the method coerces to (frequently in `.try_convert` method), or in `Object`. That's true for `to_s`/`to_str`, `to_a`/`to_ary`, `to_enum`, `to_io`, and creates pretty strong intuition of "if we want it to be compatible with class X, there are some `to_<x>` or alike methods to be implemented".

`#to_str` and `#to_s` differ in explicitness, and `#to_proc` is in the `#to_s` side.

> I am aware the `#call` convention is somewhat embraced in some **third-party** projects. But currently, **inside** language, there is no "implied intuition" about `#call` method. We have a small syntactic sugar feature of `.()`, which is rarely used in language docs, and no core classes except for Proc and Method have a `#call` method (but they also both have `#to_proc`); other objects "quacking like callable" use `#to_proc` to designate this fact. The discrepancy between two is hard to explain and document, and I believe that there would be a lot of confusion with this feature. 

`#call` method is called by `Enumerable`, `Enumerator`, finalizer and `eval`.

> PS: I just wonder, why `#call` convention was chosen over `#to_proc`, initially?..

As stated already, `#to_proc` is an explicit conversion, so it would not called implicitly.


----------------------------------------
Bug #15428: Refactor Proc#>> and #<<
https://bugs.ruby-lang.org/issues/15428#change-76263

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
* ruby -v: 
* Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: UNKNOWN
----------------------------------------
#6284 introduced `Proc#>>` and `Proc#<<`, but the requirements to the argument is totally inconsistent with ANY other place in Ruby.

Currently, it is the **only** place in Ruby where coercing argument to `Proc` is done with `#call` method. Everywhere else it is done with `#to_proc`, and `#call` method never had any special significance except for `.()` sugar. I believe there are two possible actions:

1. change `#>>` and `#<<` to use `#to_proc` (which will give Symbols composability for free), **or, alternatively**
2. state that `#call` from now on has a special meaning in Ruby and probably decide on other APIs that should respect it (for example, auto-define `#to_proc` on any object that has `#call`)

Either is OK, the current situation is not.

PS: One more problem (that probably should be discussed separately) is that check for `#call` existence is performed pretty late, which can lead to this kind of errors:

```ruby
# At code loading time:

# I erroneously thought this is correct. It is not, but the line would perform without
# any error.
PROCESSOR = JSON.method(:parse) >> :symbolize_keys 

# Later, in runtime:
'{"foo": "bar"}'.then(&PROCESSOR)
# NoMethodError (undefined method `call' for :symbolize_keys:Symbol)
```

**UPD 2018-12-29:** As this ticket was ignored prior to 2.6 release, I rewrote it in an "actionable" instead of "question" manner. 



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>