From: nobu@... Date: 2019-01-13T07:08:40+00:00 Subject: [ruby-core:91058] [Ruby trunk Bug#15428] Refactor Proc#>> and #<< Issue #15428 has been updated by nobu (Nobuyoshi Nakada). zverok (Victor Shepelev) wrote: > Now, from what I can understand, you followed this rule of thumb: > * if something is passed with `&`, it is converted with `to_proc` (it is something that _have some method of coercion_ to a Proc) > * if something is passed as a regular argument, to call later, it is used with `call` (it is something that _think of itself as a kind of Proc_) Right. > So, in fact, it is my "option 2": "codify that `#call` from now on has a special meaning in Ruby", and considering your answer, it is kinda already done since the beginning of time, just not very obvious :) More precisely, a special meaning to the Proc class, and other classes expect the role. > OK, I can spot 3 problems here: > 1. It is not very obvious from documentation and general language structure, as I mentioned above > 2. Unlike any other implicit/explicit pairs, "argument construction operator" uses _explicit_ conversion method (`*` uses `#to_ary` and `**` uses `#to_hash`) > 3. There is no means/helpers/practices to draw explicit method from implicit (though implicit is easier to define) As for (2), `*` uses `#to_a` whereas `**` uses `#to_hash`, I agree that there is an inconsistency. > I believe that (2) is what we'll just need to live with, but both (1) and (3) could be solved with introducing core module `Callable` (akin to `Enumerable` and `Comparable`), defined, let's say, like this: > ```ruby > module Callable > def to_proc > proc { |*a, &b| call(*a, &b) } > end > end > ``` > That's not so much "non-trivial code", as "atomic declaration of statement": "this thing is callable; Proc and Method are callable, but you can define your own; proc composition composes any callable objects". I'm neutral about it, [callable gem] seems existing. [callable gem]: https://rubygems.org/gems/callable ---------------------------------------- Bug #15428: Refactor Proc#>> and #<< https://bugs.ruby-lang.org/issues/15428#change-76276 * 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: