[#109403] [Ruby master Feature#18951] Object#with to set and restore attributes around a block — "byroot (Jean Boussier)" <noreply@...>

Issue #18951 has been reported by byroot (Jean Boussier).

23 messages 2022/08/01

[#109423] [Ruby master Misc#18954] DevMeeting-2022-08-18 — "mame (Yusuke Endoh)" <noreply@...>

Issue #18954 has been reported by mame (Yusuke Endoh).

10 messages 2022/08/04

[#109449] [Ruby master Feature#18959] Handle gracefully nil kwargs eg. **nil — "LevLukomskyi (Lev Lukomskyi)" <noreply@...>

Issue #18959 has been reported by LevLukomskyi (Lev Lukomskyi).

27 messages 2022/08/08

[#109456] [Ruby master Bug#18960] Module#using raises RuntimeError when called at toplevel from wrapped script — "shioyama (Chris Salzberg)" <noreply@...>

Issue #18960 has been reported by shioyama (Chris Salzberg).

15 messages 2022/08/09

[#109550] [Ruby master Feature#18965] Further Thread::Queue improvements — "byroot (Jean Boussier)" <noreply@...>

Issue #18965 has been reported by byroot (Jean Boussier).

14 messages 2022/08/18

[#109575] [Ruby master Bug#18967] Segmentation fault in stackprof with Ruby 2.7.6 — "RubyBugs (A Nonymous)" <noreply@...>

Issue #18967 has been reported by RubyBugs (A Nonymous).

10 messages 2022/08/19

[#109598] [Ruby master Bug#18970] CRuby adds an invalid header to bin/bundle (and others) which makes it unusable in Bash on Windows — "Eregon (Benoit Daloze)" <noreply@...>

Issue #18970 has been reported by Eregon (Benoit Daloze).

17 messages 2022/08/20

[#109645] [Ruby master Bug#18973] Kernel#sprintf: %c allows codepoints above 127 for 7-bits ASCII encoding — "andrykonchin (Andrew Konchin)" <noreply@...>

Issue #18973 has been reported by andrykonchin (Andrew Konchin).

8 messages 2022/08/23

[#109689] [Ruby master Misc#18977] DevMeeting-2022-09-22 — "mame (Yusuke Endoh)" <noreply@...>

Issue #18977 has been reported by mame (Yusuke Endoh).

16 messages 2022/08/25

[#109707] [Ruby master Feature#18980] Re-reconsider numbered parameters: `it` as a default block parameter — "k0kubun (Takashi Kokubun)" <noreply@...>

Issue #18980 has been reported by k0kubun (Takashi Kokubun).

40 messages 2022/08/26

[#109756] [Ruby master Feature#18982] Add an `exception: false` argument for Queue#push, Queue#pop, SizedQueue#push and SizedQueue#pop — "byroot (Jean Boussier)" <noreply@...>

Issue #18982 has been reported by byroot (Jean Boussier).

11 messages 2022/08/29

[#109773] [Ruby master Misc#18984] Doc for Range#size for Float/Rational does not make sense — "masasakano (Masa Sakano)" <noreply@...>

Issue #18984 has been reported by masasakano (Masa Sakano).

7 messages 2022/08/29

[ruby-core:109509] [Ruby master Feature#17330] Object#non

From: "zverok (Victor Shepelev)" <noreply@...>
Date: 2022-08-17 05:13:47 UTC
List: ruby-core #109509
Issue #17330 has been updated by zverok (Victor Shepelev).


TBH, I believe that core method names should be short, recognizable and elegant in context in the first place, not explaining what they do in multiple words.
We are thinking about "learn once, use 1000 times" here first, not only about a period of introduction of the new method.

It is the same as `yield_self`, which kinda "said what it did" but looked ugly and over-explaining for everyday use and was promptly renamed to `then`.
The same is related to the idea of `itself_if`/`itself_unless`, I believe (it is like using `each_returning_result` instead of `map`).

Just `#if` and `#unless` look tempting, though.

----------------------------------------
Feature #17330: Object#non
https://bugs.ruby-lang.org/issues/17330#change-98678

* Author: zverok (Victor Shepelev)
* Status: Open
* Priority: Normal
----------------------------------------
(As always "with core" method proposals, I don't expect quick success, but hope for a fruitful discussion)

### Reasons:

Ruby always tried to be very chainability-friendly. Recently, with introduction of `.then` and `=>`, even more so. But one pattern that frequently emerges and doesn't have good idiomatic expression: calculate something, and if it is not a "good" value, return `nil` (or provide default value with `||`). There are currently two partial solutions:

1. `nonzero?` in Ruby core (frequently mocked for "inadequate" behavior, as it is looking like predicate method, but instead of `true`/`false` returns an original value or `nil`)
2. ActiveSupport `Object#presence`, which also returns an original value or `nil` if it is not "present" (e.g. `nil` or `empty?` in AS-speak)

Both of them prove themselves quite useful in some domains, but they are targeting only those particular domains, look unlike each other, and can be confusing.

### Proposal:

Method `Object#non` (or `Kernel#non`), which receives a block, calls it with receiver and returns `nil` (if block matched) or receiver otherwise.

##### Prototype implementation:

```ruby
class Object
  def non
    self unless yield(self)
  end
end
```

##### Usage examples:

1. With number:

    ```ruby
    limit = calculate.some.limit
    limit.zero? ? DEFAULT_LIMIT : limit
    # or, with nonzero?
    calculate.some.limit.nonzero? || DEFAULT_LIMIT
    # with non:
    calculate.some.limit.non(&:zero?) || DEFAULT_LIMIT
    # ^ Note here, how, unlike `nonzero?`, we see predicate-y ?, but it is INSIDE the `non()` and less confusing
    ```

2. With string:

    ```ruby
    name = params[:name] if params[:name] && !params[:name].empty?
    # or, with ActiveSupport:
    name = params[:name].presence
    # with non:
    name = params[:name]&.non(&:empty?)
    ```

3. More complicated example

    ```ruby
    action = payload.dig('action', 'type')
    return if PROHIBITED_ACTIONS.include?(action)
    send("do_#{action}")
    # with non & then:
    payload.dig('action', 'type')
      .non { |action| PROHIBITED_ACTIONS.include?(action) }
      &.then { |action| send("do_#{action}") }
    ```

Basically, the proposal is a "chainable guard clause" that allows to "chain"ify and DRYify code like:

```ruby
value = fetch_something
return value unless value.with_problems?
# which turns into
fetch_something.non(&:with_problems?)

# or
value = fetch_something
value = reasonable_default if value.with_problems?
# turns into
value = fetch_something.non(&:with_problems?) || reasonable_default
```

I believe that this idiom is frequent enough, in combinations like (assorted examples) "read config file but return `nil` if it is empty/wrong version", "fetch latest invoice, but ignore if it has an `unpayable` flag", "fetch a list of last user's searches, but if it is empty, provide default search hints" etc.

I believe there _is_ un unreflected need for idiom like this, the need that is demonstrated by the existence of `nonzero?` and `presence`.



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

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread