ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:90591] [Ruby trunk Misc#15428] Proc composition: what can quack like Proc?
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
@ 2018-12-17 21:56 ` zverok.offline
  2018-12-17 22:00 ` [ruby-core:90592] " zverok.offline
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: zverok.offline @ 2018-12-17 21:56 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been reported by zverok (Victor Shepelev).

----------------------------------------
Misc #15428: Proc composition: what can quack like Proc?
https://bugs.ruby-lang.org/issues/15428

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I believe, that solution of #6284 introduced important language inconsistency: as far as I can tell, it insists that **anything that responds to `#call`** is composable, e.g. **quacks like `Proc`**.

The problem is, previously it was **never** this way. `#call` method has a nice shortcut of `.()`, but when you wanted to tell something can quack like proc, it **always** was done by defining `#to_proc` method.

I understand it could be too late to ask, but I wonder why this inconsistency was introduced and is there a plan to take this step further? 
For me personally, this `#call`/`#to_proc` dichotomy was always weird and feels like it needs some unification (maybe anything having `#call` will automatically have `#to_proc` method?), but the situation when exactly one language feature treats it differently looks pretty weird for me.



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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:90592] [Ruby trunk Misc#15428] Proc composition: what can quack like Proc?
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
  2018-12-17 21:56 ` [ruby-core:90591] [Ruby trunk Misc#15428] Proc composition: what can quack like Proc? zverok.offline
@ 2018-12-17 22:00 ` zverok.offline
  2018-12-18 22:33 ` [ruby-core:90611] " shevegen
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: zverok.offline @ 2018-12-17 22:00 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been updated by zverok (Victor Shepelev).


BTW, having `>>` and `<<` convert objects via `to_proc` would have a nice (?) addition of chaining symbols too:

```ruby
PROCESS = ->(url) { get(url) } >> JSON.method(:parse) >> :symbolize_keys >> :invert
```

----------------------------------------
Misc #15428: Proc composition: what can quack like Proc?
https://bugs.ruby-lang.org/issues/15428#change-75745

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I believe, that solution of #6284 introduced important language inconsistency: as far as I can tell, it insists that **anything that responds to `#call`** is composable, e.g. **quacks like `Proc`**.

The problem is, previously it was **never** this way. `#call` method has a nice shortcut of `.()`, but when you wanted to tell something can quack like proc, it **always** was done by defining `#to_proc` method.

I understand it could be too late to ask, but I wonder why this inconsistency was introduced and is there a plan to take this step further? 
For me personally, this `#call`/`#to_proc` dichotomy was always weird and feels like it needs some unification (maybe anything having `#call` will automatically have `#to_proc` method?), but the situation when exactly one language feature treats it differently looks pretty weird for me.



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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:90611] [Ruby trunk Misc#15428] Proc composition: what can quack like Proc?
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
  2018-12-17 21:56 ` [ruby-core:90591] [Ruby trunk Misc#15428] Proc composition: what can quack like Proc? zverok.offline
  2018-12-17 22:00 ` [ruby-core:90592] " zverok.offline
@ 2018-12-18 22:33 ` shevegen
  2019-01-12  9:36 ` [ruby-core:91035] [Ruby trunk Bug#15428][Open] Refactor Proc#>> and #<< zverok.offline
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: shevegen @ 2018-12-18 22:33 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been updated by shevegen (Robert A. Heiler).


Are you sure that .call had the same meaning as to_proc?

I vaguely remember the old pickaxe having mentioned .call a
lot, but I can not recall it having mentioned to_proc much
at all. It has been quite some years since I last had a look
at it though; obviously since ruby changes that also means
that the way we use ruby changes.

As for the lambda syntax and << - I think it would be better
to keep the proposals different if possible since at the 
least to me, ->(x) { y } << z looks ... very, very weird.

It would be better to keep the issue here about call versus
to_proc, in my opinion.

----------------------------------------
Misc #15428: Proc composition: what can quack like Proc?
https://bugs.ruby-lang.org/issues/15428#change-75770

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
* Assignee: 
----------------------------------------
I believe, that solution of #6284 introduced important language inconsistency: as far as I can tell, it insists that **anything that responds to `#call`** is composable, e.g. **quacks like `Proc`**.

The problem is, previously it was **never** this way. `#call` method has a nice shortcut of `.()`, but when you wanted to tell something can quack like proc, it **always** was done by defining `#to_proc` method.

I understand it could be too late to ask, but I wonder why this inconsistency was introduced and is there a plan to take this step further? 
For me personally, this `#call`/`#to_proc` dichotomy was always weird and feels like it needs some unification (maybe anything having `#call` will automatically have `#to_proc` method?), but the situation when exactly one language feature treats it differently looks pretty weird for me.



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

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91035] [Ruby trunk Bug#15428][Open] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2018-12-18 22:33 ` [ruby-core:90611] " shevegen
@ 2019-01-12  9:36 ` zverok.offline
  2019-01-12 11:35 ` [ruby-core:91039] [Ruby trunk Bug#15428] " nobu
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: zverok.offline @ 2019-01-12  9:36 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been updated by zverok (Victor Shepelev).

Status changed from Closed to Open

Sorry for my arrogance, but I am kinda surprised (to say the least) with how this ticket is treated.

* Ticket is closed silently (are you aware that it is an event when Redmine doesn't send the notification, so unless I'll check manually, I am not aware that ticket is closed?)
* [Developer meeting discussion log](https://docs.google.com/document/u/1/d/1W_wrFsFxxU1MepA6HBpfl-9h-nLD8EBsgMsS7yTDvHE/pub) seems to completely miss the point of the ticket. Quoting from there:

  > **Mame**: Use a block.  You then want syntactic sugar for passing an argument, and then for partial application, blah blah blah.
  > **knu**: We should not add fancy new features around procs and symbols if the real problem is that block syntax is not good enough, like `|x|` is always necessary. (See above for the default block parameter syntax)

I understand that typical problem with my "large" tickets is I am trying to consider too much things (believing it would describe the problem better), and sometimes it is too hard to tell what's my _main_ point. So I should try better.

---

**Main point of this ticket:** Special treatment of `#call` in `Proc#>>` and `Proc#<<` is **inconsistent** with the rest of the language.

There are **two possible solutions** for this problem:

1. **change `#>>` and `#<<` to use `#to_proc`**, or, alternatively
2. **codify that `#call` from now on has a special meaning** in Ruby and probably decide on other APIs that should respect it

This ticket is NOT about "I want to chain symbols, it is nice". What I want is **language consistency**, not **fancy new features**. In fact, I want exactly the opposite as "fancy new features (that ignore consistency)", which current implementation of `#>>`/`#<<` apparently is.

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

* 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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91039] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2019-01-12  9:36 ` [ruby-core:91035] [Ruby trunk Bug#15428][Open] Refactor Proc#>> and #<< zverok.offline
@ 2019-01-12 11:35 ` nobu
  2019-01-12 12:08 ` [ruby-core:91041] " zverok.offline
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: nobu @ 2019-01-12 11:35 UTC (permalink / raw)
  To: ruby-core

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


Sorry, I was going to reopen this after r66769, but have forgotten.

> Currently, it is the **only** place in Ruby where coercing argument to `Proc` is done with `#call` method. 

These methods do not coerce argument, but just expect a method on it.

> 1. change `#>>` and `#<<` to use `#to_proc`

`#to_proc` is not an implicit conversion method, as it needs the specific syntax, `&`.

> 2. state that `#call` from now on has a special meaning in Ruby

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.



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

* 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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91041] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2019-01-12 11:35 ` [ruby-core:91039] [Ruby trunk Bug#15428] " nobu
@ 2019-01-12 12:08 ` zverok.offline
  2019-01-12 12:31 ` [ruby-core:91042] " nobu
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: zverok.offline @ 2019-01-12 12:08 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been updated by zverok (Victor Shepelev).


> `#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.

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

```ruby
foo = "test"
foo + bar # foo is a String, the operator requires bar to have #to_str, coercing it to a compatible type
foo = -> { puts "test" }
foo << bar # foo is a Proc, the operator requires bar to have #to_proc, coercing it to a compatible type 
```

I believe that it is not just a "requirement for particular method", but consistent language rule.

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

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. 

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

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

* 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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91042] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2019-01-12 12:08 ` [ruby-core:91041] " zverok.offline
@ 2019-01-12 12:31 ` nobu
  2019-01-12 12:35 ` [ruby-core:91043] " nobu
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: nobu @ 2019-01-12 12:31 UTC (permalink / raw)
  To: ruby-core

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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91043] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (6 preceding siblings ...)
  2019-01-12 12:31 ` [ruby-core:91042] " nobu
@ 2019-01-12 12:35 ` nobu
  2019-01-12 13:24 ` [ruby-core:91044] " zverok.offline
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 11+ messages in thread
From: nobu @ 2019-01-12 12:35 UTC (permalink / raw)
  To: ruby-core

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


nobu (Nobuyoshi Nakada) wrote:
> `#call` method is called by `Enumerable`, `Enumerator`, finalizer and `eval`.

Sorry, the last is `Signal`, not `eval`.

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

* 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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91044] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (7 preceding siblings ...)
  2019-01-12 12:35 ` [ruby-core:91043] " nobu
@ 2019-01-12 13:24 ` zverok.offline
  2019-01-13  7:08 ` [ruby-core:91058] " nobu
  2019-01-20 20:04 ` [ruby-core:91195] " eregontp
  10 siblings, 0 replies; 11+ messages in thread
From: zverok.offline @ 2019-01-12 13:24 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been updated by zverok (Victor Shepelev).


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

That's interesting. I just looked through the docs and understood I was not very aware of this fact:
* `Enumerable#find` (is the only method using `#call`, right?) says just "calls _ifnone_ and returns its result", not specifying how exactly it "calls";
* `Enumerator::new` says "callable object" without further explanation;
* `Signal#trap` says "Otherwise, the given command or block will be run".

OK, that' the problem of docs, I'll handle it. I also never have seen either used in the wild (in a form of "callable object passing"), but maybe it is just me.

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

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

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)

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

Usage in some client code:
```ruby
class SetStatus < BusinessAction
  def self.call(task, status)
    new(task, status).validate.call # ...or something
  end

  extend Callable
end

tasks_and_statuses.each(&SetStatus)
```

WDYT?

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

* 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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91058] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (8 preceding siblings ...)
  2019-01-12 13:24 ` [ruby-core:91044] " zverok.offline
@ 2019-01-13  7:08 ` nobu
  2019-01-20 20:04 ` [ruby-core:91195] " eregontp
  10 siblings, 0 replies; 11+ messages in thread
From: nobu @ 2019-01-13  7:08 UTC (permalink / raw)
  To: ruby-core

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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [ruby-core:91195] [Ruby trunk Bug#15428] Refactor Proc#>> and #<<
       [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
                   ` (9 preceding siblings ...)
  2019-01-13  7:08 ` [ruby-core:91058] " nobu
@ 2019-01-20 20:04 ` eregontp
  10 siblings, 0 replies; 11+ messages in thread
From: eregontp @ 2019-01-20 20:04 UTC (permalink / raw)
  To: ruby-core

Issue #15428 has been updated by Eregon (Benoit Daloze).


@nobu I think we should backport r66769 to Ruby 2.6, could you do it or file an issue for it?

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

* 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/

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2019-01-20 20:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-15428.20181217215635@ruby-lang.org>
2018-12-17 21:56 ` [ruby-core:90591] [Ruby trunk Misc#15428] Proc composition: what can quack like Proc? zverok.offline
2018-12-17 22:00 ` [ruby-core:90592] " zverok.offline
2018-12-18 22:33 ` [ruby-core:90611] " shevegen
2019-01-12  9:36 ` [ruby-core:91035] [Ruby trunk Bug#15428][Open] Refactor Proc#>> and #<< zverok.offline
2019-01-12 11:35 ` [ruby-core:91039] [Ruby trunk Bug#15428] " nobu
2019-01-12 12:08 ` [ruby-core:91041] " zverok.offline
2019-01-12 12:31 ` [ruby-core:91042] " nobu
2019-01-12 12:35 ` [ruby-core:91043] " nobu
2019-01-12 13:24 ` [ruby-core:91044] " zverok.offline
2019-01-13  7:08 ` [ruby-core:91058] " nobu
2019-01-20 20:04 ` [ruby-core:91195] " eregontp

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).