* [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
@ 2024-08-03 16:41 knu (Akinori MUSHA) via ruby-core
2024-08-03 17:31 ` [ruby-core:118785] " zverok (Victor Shepelev) via ruby-core
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: knu (Akinori MUSHA) via ruby-core @ 2024-08-03 16:41 UTC (permalink / raw)
To: ruby-core; +Cc: knu (Akinori MUSHA)
Issue #20664 has been reported by knu (Akinori MUSHA).
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118785] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
@ 2024-08-03 17:31 ` zverok (Victor Shepelev) via ruby-core
2024-08-03 18:22 ` [ruby-core:118786] " knu (Akinori MUSHA) via ruby-core
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: zverok (Victor Shepelev) via ruby-core @ 2024-08-03 17:31 UTC (permalink / raw)
To: ruby-core; +Cc: zverok (Victor Shepelev)
Issue #20664 has been updated by zverok (Victor Shepelev).
I am not sure about this API.
I think in language core there aren’t many APIs that accept just a symbol of a necessary method (only `reduce(:+)` comes to mind, and I am still not sure why this form exists, because it seems to have been introduced at the same time when `Symbol#to_proc` was, so `reduce(:+)` and `reduce(&:+)` were always co-existing).
Mostly callables are passed as a block (and therefore there can be only one); but some APIs accept another callable (any object with `#call` method, like Enumerator.new).
So, what if condition is _not_ an method of the sequence?.. Should we accept callables, too? Or, what if the method’s user expects it to be a particular value (like `until: 0`), or a pattern (like `before: 0..1`).
The alternative is
```ruby
Enumerator.produce(File, &:superclass).take_until(&:nil?)
```
...which is more or less the same character-count-wise, more powerful (any block can be used), and more atomic.
The one problem we don’t currently have neither `Enumerable#take_until`, nor `Object#not_nil?`, to write something like
```ruby
# this wouldn’t work
Enumerator.produce(File, &:superclass).take_while(&:not_nil?)
# though one can use
Enumerator.produce(File, &:superclass).take_while(&:itself)
#=> [File, IO, Object, BasicObject]
```
...but in general, I suspect adding `Enumerable#take_until` to handle such cases ([and `#take_while_after`](https://bugs.ruby-lang.org/issues/18136) while we are on it :)) might be more powerful addition to the language, useful in many situations.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109340
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118786] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
2024-08-03 17:31 ` [ruby-core:118785] " zverok (Victor Shepelev) via ruby-core
@ 2024-08-03 18:22 ` knu (Akinori MUSHA) via ruby-core
2024-08-03 18:39 ` [ruby-core:118787] " knu (Akinori MUSHA) via ruby-core
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: knu (Akinori MUSHA) via ruby-core @ 2024-08-03 18:22 UTC (permalink / raw)
To: ruby-core; +Cc: knu (Akinori MUSHA)
Issue #20664 has been updated by knu (Akinori MUSHA).
This proposal is based on the potential use cases I have experienced over the years. I've rarely seen a need for infinite sequences that can be defined with produce, and that is why I want to give produce() a feature-complete constructor.
Almost all sequences have had clear and simple end conditions. Traversing a tree structure for ancestor or sibling nodes would be the most typical use case, and the predicates like `nil?` and `root?` are mostly enough. Type-based conditions and inclusion conditions are not much seen probably because sequences are likely to be homogeneous and there is rarely more than one or a range of terminal values.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109341
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118787] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
2024-08-03 17:31 ` [ruby-core:118785] " zverok (Victor Shepelev) via ruby-core
2024-08-03 18:22 ` [ruby-core:118786] " knu (Akinori MUSHA) via ruby-core
@ 2024-08-03 18:39 ` knu (Akinori MUSHA) via ruby-core
2024-08-19 21:05 ` [ruby-core:118896] " matheusrich (Matheus Richard) via ruby-core
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: knu (Akinori MUSHA) via ruby-core @ 2024-08-03 18:39 UTC (permalink / raw)
To: ruby-core; +Cc: knu (Akinori MUSHA)
Issue #20664 has been updated by knu (Akinori MUSHA).
These options should take callables in this proposal. Procs and Methods certainly meet the condition: "Any value that responds to to_proc and returns a Proc object is accepted in these options".
The implementation does not bother to call `to_proc` on Procs, though.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109343
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118896] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (2 preceding siblings ...)
2024-08-03 18:39 ` [ruby-core:118787] " knu (Akinori MUSHA) via ruby-core
@ 2024-08-19 21:05 ` matheusrich (Matheus Richard) via ruby-core
2024-08-19 23:51 ` [ruby-core:118902] " ufuk (Ufuk Kayserilioglu) via ruby-core
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: matheusrich (Matheus Richard) via ruby-core @ 2024-08-19 21:05 UTC (permalink / raw)
To: ruby-core; +Cc: matheusrich (Matheus Richard)
Issue #20664 has been updated by matheusrich (Matheus Richard).
> The one problem we don’t currently have neither Enumerable#take_until, nor Object#not_nil?, to write something like
After [proposing `Object#chain_of`](https://bugs.ruby-lang.org/issues/20625), I realized how missing one of these really makes things harder than they need to.
With 3.4's `it`, the expression gets a bit more readable:
```ruby
Enumerator.produce(File, &:superclass).take_while { !it.nil? }
```
IMO this pattern is common enough to deserve an optimization. `#not_nil?` would probably be harder to add (people will start talking about `present?` and how it is longer than `!<>.nil?`, so maybe proposing `#take_until` will be easier to get approval.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109465
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118902] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (3 preceding siblings ...)
2024-08-19 21:05 ` [ruby-core:118896] " matheusrich (Matheus Richard) via ruby-core
@ 2024-08-19 23:51 ` ufuk (Ufuk Kayserilioglu) via ruby-core
2024-08-25 18:24 ` [ruby-core:118955] " zverok (Victor Shepelev) via ruby-core
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: ufuk (Ufuk Kayserilioglu) via ruby-core @ 2024-08-19 23:51 UTC (permalink / raw)
To: ruby-core; +Cc: ufuk (Ufuk Kayserilioglu)
Issue #20664 has been updated by ufuk (Ufuk Kayserilioglu).
@matheusrich In my opinion `take_until` might be an interesting method to add, but I think we are unnecessarily complicating the example with `it` and `nil?`.
The expression is simply:
```ruby
Enumerator.produce(File, &:superclass).take_while(&:itself)
```
and it works perfectly fine and, IMO, is very readable for anyone who knows enough to reach for `Enumerable.produce` in the first place.
With respect to the original proposal in this ticket, I also find it a little awkward when Ruby methods take something callable other than blocks, but I understand the pragmatic use of the proposed `to_proc`able keyword arguments that would satisfy the majority of cases where one would reach for `Enumerable.produce`.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109471
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118955] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (4 preceding siblings ...)
2024-08-19 23:51 ` [ruby-core:118902] " ufuk (Ufuk Kayserilioglu) via ruby-core
@ 2024-08-25 18:24 ` zverok (Victor Shepelev) via ruby-core
2024-08-26 12:14 ` [ruby-core:118959] " Eregon (Benoit Daloze) via ruby-core
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: zverok (Victor Shepelev) via ruby-core @ 2024-08-25 18:24 UTC (permalink / raw)
To: ruby-core; +Cc: zverok (Victor Shepelev)
Issue #20664 has been updated by zverok (Victor Shepelev).
> These options should take callables in this proposal. Procs and Methods certainly meet the condition: "Any value that responds to to_proc and returns a Proc object is accepted in these options".
Oh, yeah, sorry, missed this part, focused just on Symbol examples.
Interesting, I don’t think we have any API in core like this—accepting anything to convert it `#to_proc` implicitly. Usually when the second callable needed, the agreement is that it should respond to `#call`, not to `#to_proc` (examples: `Proc#>>`, `Enumerator#new`).
I am not sure it is “how it should be” (not a lot of APIs like this anyway), but approach with `#to_proc`-able things passed in many keyword arguments seems more Rails-ish. Maybe it is time to accept it.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109528
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118959] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (5 preceding siblings ...)
2024-08-25 18:24 ` [ruby-core:118955] " zverok (Victor Shepelev) via ruby-core
@ 2024-08-26 12:14 ` Eregon (Benoit Daloze) via ruby-core
2024-08-26 12:38 ` [ruby-core:118960] " matheusrich (Matheus Richard) via ruby-core
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2024-08-26 12:14 UTC (permalink / raw)
To: ruby-core; +Cc: Eregon (Benoit Daloze)
Issue #20664 has been updated by Eregon (Benoit Daloze).
One issue with `take_until` is: does it include the element for which it yielded `true`?
In the description example `Enumerator.produce(3, until: :zero?, &:pred)` the result does include `0`.
But for `Enumerator.produce(parent, &:parent_directory).take_until(&:nil?)` the intention is to not include `nil` in the result.
Maybe we should have 2 variants of `take_until`, or a keyword argument whether to include the last element or not.
IMO `before:/until:` kwargs for `Enumerator.produce` feel too ad-hoc.
`take_until` is something I wished existed already.
But we need to address whether it includes the last element or not.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109531
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118960] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (6 preceding siblings ...)
2024-08-26 12:14 ` [ruby-core:118959] " Eregon (Benoit Daloze) via ruby-core
@ 2024-08-26 12:38 ` matheusrich (Matheus Richard) via ruby-core
2024-08-26 16:13 ` [ruby-core:118962] " Eregon (Benoit Daloze) via ruby-core
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: matheusrich (Matheus Richard) via ruby-core @ 2024-08-26 12:38 UTC (permalink / raw)
To: ruby-core; +Cc: matheusrich (Matheus Richard)
Issue #20664 has been updated by matheusrich (Matheus Richard).
IMO `take_until` shouldn't include the element. So the OP example should be:
```rb
Enumerator.produce(3, &:pred).take_until(&:negative?)
```
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109532
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118962] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (7 preceding siblings ...)
2024-08-26 12:38 ` [ruby-core:118960] " matheusrich (Matheus Richard) via ruby-core
@ 2024-08-26 16:13 ` Eregon (Benoit Daloze) via ruby-core
2024-08-28 11:36 ` [ruby-core:118974] " zverok (Victor Shepelev) via ruby-core
2024-08-28 14:07 ` [ruby-core:118978] " matheusrich (Matheus Richard) via ruby-core
10 siblings, 0 replies; 12+ messages in thread
From: Eregon (Benoit Daloze) via ruby-core @ 2024-08-26 16:13 UTC (permalink / raw)
To: ruby-core; +Cc: Eregon (Benoit Daloze)
Issue #20664 has been updated by Eregon (Benoit Daloze).
I think that makes sense, as an opposite of `take_while`:
* `take_while` takes all elements until the block returns falsy, and does not include that element which yielded falsy.
* `take_until` takes all elements until the block returns truthy, and does not include that element which yielded truthy.
If clearly documented that probably solves most of the confusion.
So +1 from me to add `take_until`.
I wonder if there is value in having variants that do include the element that stops, but at least so far in the linked issues there seems to be no such use-case.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109534
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118974] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (8 preceding siblings ...)
2024-08-26 16:13 ` [ruby-core:118962] " Eregon (Benoit Daloze) via ruby-core
@ 2024-08-28 11:36 ` zverok (Victor Shepelev) via ruby-core
2024-08-28 14:07 ` [ruby-core:118978] " matheusrich (Matheus Richard) via ruby-core
10 siblings, 0 replies; 12+ messages in thread
From: zverok (Victor Shepelev) via ruby-core @ 2024-08-28 11:36 UTC (permalink / raw)
To: ruby-core; +Cc: zverok (Victor Shepelev)
Issue #20664 has been updated by zverok (Victor Shepelev).
About does/doesn’t include the last element, there is a related inconclusive discussion: #18136
Basically, I believe that both `take_while`/`take_until` might have pairs of use cases:
```ruby
# the last element not necessary
sequence.take_until(&:bad?)
# the last element is necessary: think `.` in a sentence
sequence.take_until(&:terminator?)
# the last element is not necessary
sequence.take_while(&:suitable?)
# the last element is necessary: think the last page on pagination
# (which doesn’t match the condition “have more pages” but is a meaningful element itself)
sequence.take_while(&:last_matching_element?)
```
(We have a `#take_while_after` in our `core_ext.rb`, and use it regularly.)
The `Enumerable#slice_after` and `#slice_before`, for example, recognize that it might be either, but not `take_while`.
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109547
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
* [ruby-core:118978] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
` (9 preceding siblings ...)
2024-08-28 11:36 ` [ruby-core:118974] " zverok (Victor Shepelev) via ruby-core
@ 2024-08-28 14:07 ` matheusrich (Matheus Richard) via ruby-core
10 siblings, 0 replies; 12+ messages in thread
From: matheusrich (Matheus Richard) via ruby-core @ 2024-08-28 14:07 UTC (permalink / raw)
To: ruby-core; +Cc: matheusrich (Matheus Richard)
Issue #20664 has been updated by matheusrich (Matheus Richard).
The kwargs proposed here could be useful:
```rb
sequence.take_until(inclusive: true, &:terminator?)
```
Alternatively, we could always be inclusive and let people `pop` to remove the last element:
```rb
sequence.take_until(&:terminator?).pop
```
----------------------------------------
Feature #20664: Add `before` and `until` options to Enumerator.produce
https://bugs.ruby-lang.org/issues/20664#change-109551
* Author: knu (Akinori MUSHA)
* Status: Open
----------------------------------------
Enumerator.produce provides a nice way to generate an infinite sequence but is a bit awkward to define how to end a sequence. It lacks a simple and easy way to produce typical finite sequences in an intuitive syntax.
This proposal attempts to solve the problem by adding these two options to the method:
- `before`: when provided, it is used as a predicate to determine if an iteration should end before a generated value gets yielded.
- `until`: when provided, it is used as a predicate to determine if an iteration should end until after a generated value gets yielded.
Any value that responds to `to_proc` and returns a `Proc` object is accepted in these options.
A typical use case for the `before` option is traversing a tree structure to iterate over the ancestors or following/preceding siblings of a node.
The `until` option can be used when there is a clear definition of the "last" value to yield.
```ruby
enum = Enumerator.produce(File, before: :nil?, &:superclass)
enum.to_a #=> [File, IO, Object, BasicObject]
enum = Enumerator.produce(3, until: :zero?, &:pred)
enum_to_a #=> [3, 2, 1, 0]
```
---Files--------------------------------
0001-Add-before-and-until-options-to-Enumerator.produce.patch (10.7 KB)
--
https://bugs.ruby-lang.org/
______________________________________________
ruby-core mailing list -- ruby-core@ml.ruby-lang.org
To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-08-28 14:07 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-03 16:41 [ruby-core:118784] [Ruby master Feature#20664] Add `before` and `until` options to Enumerator.produce knu (Akinori MUSHA) via ruby-core
2024-08-03 17:31 ` [ruby-core:118785] " zverok (Victor Shepelev) via ruby-core
2024-08-03 18:22 ` [ruby-core:118786] " knu (Akinori MUSHA) via ruby-core
2024-08-03 18:39 ` [ruby-core:118787] " knu (Akinori MUSHA) via ruby-core
2024-08-19 21:05 ` [ruby-core:118896] " matheusrich (Matheus Richard) via ruby-core
2024-08-19 23:51 ` [ruby-core:118902] " ufuk (Ufuk Kayserilioglu) via ruby-core
2024-08-25 18:24 ` [ruby-core:118955] " zverok (Victor Shepelev) via ruby-core
2024-08-26 12:14 ` [ruby-core:118959] " Eregon (Benoit Daloze) via ruby-core
2024-08-26 12:38 ` [ruby-core:118960] " matheusrich (Matheus Richard) via ruby-core
2024-08-26 16:13 ` [ruby-core:118962] " Eregon (Benoit Daloze) via ruby-core
2024-08-28 11:36 ` [ruby-core:118974] " zverok (Victor Shepelev) via ruby-core
2024-08-28 14:07 ` [ruby-core:118978] " matheusrich (Matheus Richard) via ruby-core
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 NNTP newsgroup(s).