ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: shevegen@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:96434] [Ruby master Feature#16446] Enumerable#take_*, Enumerable#drop_* counterparts with positive conditions
Date: Mon, 23 Dec 2019 15:14:11 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-83356.20191223151411.4b8c8d858e5ebf6a@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-16446.20191223082605@ruby-lang.org

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


I have not thought about the proposal here quite much so far, sorry (and admittedly I may need
to do so  on a fresh morning as I am a bit tired).

Just two brief comments:

- Some of the examples remind me a bit of .select/.reject/.filter. Personally I try
to favour .select whenever possible, largely because I like positive selection/filtering.

- To your statement "In such use cases, it is more natural to describe the condition
  in positive terms (i.e., zero?) rather than negative terms (i.e., nonzero?)".

Yup, completely agree with you there. We may have to include cases that do not have a
clear decisive difference, though, such as .odd? and .even? for numbers, and perhaps
other elements similar to this.

----------------------------------------
Feature #16446: Enumerable#take_*, Enumerable#drop_* counterparts with positive conditions
https://bugs.ruby-lang.org/issues/16446#change-83356

* Author: sawa (Tsuyoshi Sawada)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
#16441 led me to think about the issue more generally. When we want to split a series of iterations by the first element that satisfies (or dissatisfies) a condition, we have three factors to consider.

(1) Whether we want the condition to work **negatively** or **positively**
(2) Whether we want the first element to satisfy (or dissatisfy) the condition to be included in the **left** side or the **right** side of the split
(3) Whether we want the **left** side or the **right** side in the returned output

This leads us to eight possible combinations to consider.

```ruby
enum = [1, 1, 0, 3, 3, 0, 5, 5].to_enum
```

| |(1)|(2)|(3)|method|example|
|--|--|--|--|--|--|
|1|negatively|left|left|`take_while`|`enum.foo1(&:nonzero?) # => [1, 1]`|
|2|negatively|left|right|`drop_while`|`enum.foo2(&:nonzero?) # => [0, 3, 3, 0, 5, 5]`|
|3|negatively|right|left||`enum.foo3(&:nonzero?) # => [1, 1, 0]`|
|4|negatively|right|right||`enum.foo4(&:nonzero?) # => [3, 3, 0, 5, 5]`|
|5|positively|left|left||`enum.foo5(&:zero?) # => [1, 1]`|
|6|positively|left|right||`enum.foo6(&:zero?) # => [0, 3, 3, 0, 5, 5]`|
|7|positively|right|left||`enum.foo7(&:zero?) # => [1, 1, 0]`|
|8|positively|right|right||`enum.foo8(&:zero?) # => [3, 3, 0, 5, 5]`|

Proposal #16441 asks for a method that corresponds to case 3 in the table above, but I think that would make the paradigm messy unless case 4 is also implemented. Either cases 3 and 4 should both be implemented, or both not. Actually, the current proposal is not about cases 3 and 4. I would leave that to #16641.

In many use cases (including the first example in #16641), we want to detect the "marker element" by which we split the iterations. In the cases above, that can be the element `0`. In such use cases, it is more natural to describe the condition in positive terms (i.e., `zero?`) rather than negative terms (i.e., `nonzero?`). (And in other use cases, it might be the other way around.) So I would like to propose methods that correspond to cases 5, 6, 7, 8 above.

Naming of the methods should be done systematically. As a candidate, I came up with the following:

||method|
|--|--|
|5|`take_before`|
|6|`drop_before`|
|7|`take_upto`|
|8|`drop_upto`|




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

  parent reply	other threads:[~2019-12-23 15:14 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-16446.20191223082605@ruby-lang.org>
2019-12-23  8:26 ` [ruby-core:96419] [Ruby master Feature#16446] Enumerable#take_*, Enumerable#drop_* counterparts with positive conditions sawadatsuyoshi
2019-12-23 15:14 ` shevegen [this message]
2019-12-23 20:29 ` [ruby-core:96440] " wishdev
2019-12-23 21:52 ` [ruby-core:96442] " sawadatsuyoshi
2019-12-23 22:12 ` [ruby-core:96443] " wishdev
2019-12-27 20:43 ` [ruby-core:96526] " daniel
2019-12-28 17:59 ` [ruby-core:96558] " sawadatsuyoshi
2020-01-16  6:56 ` [ruby-core:96893] " matz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-83356.20191223151411.4b8c8d858e5ebf6a@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).