From: "rubyFeedback (robert heiler) via ruby-core" <ruby-core@...> Date: 2023-02-23T20:02:14+00:00 Subject: [ruby-core:112557] [Ruby master Feature#18136] take_while_after Issue #18136 has been updated by rubyFeedback (robert heiler). I think one big problem with the proposed name such as the three word one is that they are somewhat rare and difficult to remember. In ruby we often have one word, or two words for methods. We may have some three words if I remember correctly, but these are quite rare, and it is a LOT harder to understand "take_while_after" or "do_this_that", than comparable ".upto()" or ".downto()" and so forth. We kind of have combined "instructions" such as: [3,4,5].each.with_index These are a bit different though. We could of course call such a combined instruction via: [3,4,5].each_with_index so just a single method with three words. But I think semantically it is easier to use .each, standalone as we do now, and then "aggregate" onto it, such as via .with_index. That conveys the meaning quite clearly. With three word names, as a single method, I think it quite a lot more difficult to convey meaning. > I'd rather choose an obvious name, like take_until_after. I think it has a very similar problem as take_while_after. ---------------------------------------- Feature #18136: take_while_after https://bugs.ruby-lang.org/issues/18136#change-102007 * Author: zverok (Victor Shepelev) * Status: Open * Priority: Normal ---------------------------------------- Sorry, I already tried that once (#16441) but I failed to produce the persuasive example. So I am back with a couple of them, much simpler and clear than my initial. **The proposal itself:** Have `take_while_after` which behaves like `take_while` but also includes the last element (first where the condition failed). Reason: there are a lot of cases where "the last good item" in enumeration is the distinctive one (one where enumeration should stop, but the item is still good. **Example 1:** Take pages from paginated API, the last page will have less items than the rest (and that's how we know it is the last): ```ruby (0..).lazy .map { |offset| get_page(offset, limit) } .take_while_after { |response| response.count == limit } # the last will have, say, 10 items, but should still be included! .map { process response somehow } ``` **Example 2:** Same as above, but "we should continue pagination" is specified with a separate data key "can_continue": ```ruby (0..).lazy .map { |offset| get_page(offset, limit) } .take_while_after { |response| response['can_continue'] } # the last will have can_continue=false, but still has data .map { process response somehow } ``` **Exampe 3:** Taking a sentence from a list of tokens like this: ```ruby tokens = [ {text: 'Ruby', type: :word}, {text: 'is', type: :word}, {text: 'cool', type: :word}, {text: '.', type: :punctuation, ends_sentence: true}, {text: 'Rust', type: :word}, # ... ] sentence = tokens.take_while_after { !_1[:ends_sentence] } ``` (I can get more if it is necessary!) Neither of those can be solved by "Using `take_while` with proper condition.", as @matz suggested here: https://bugs.ruby-lang.org/issues/16441#note-9 I typically solve it by `slice_after { condition }.first`, but that's a) uglier and b) greedy when we are working with lazy enumerator (so for API examples, all paginated pages would be fetched at once, and only then processed). Another consideration in #16441 was an unfortunate naming. I am leaving it to discussion, though I tend to like `#take_upto` from #16446. -- 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/postorius/lists/ruby-core.ml.ruby-lang.org/