From: "TylerRick (Tyler Rick) via ruby-core" Date: 2024-09-09T23:16:05+00:00 Subject: [ruby-core:119104] [Ruby master Feature#13820] Add a nil coalescing operator Issue #13820 has been updated by TylerRick (Tyler Rick). Ruby already has the safe navigation operator `?.`, added back in Ruby 2.3, which was definitely a step in the right direction with regards to first-class `nil`-aware operations. Now we just need a null coalescing operator like most other popular languages have and our support for null-aware operators will be complete! I would jump for joy. Please add this. Adding this operator would make it elegantly concise and trivially simple to just write what you mean the *first* time: "if LHS is **nil** , then use (`??`) / initialize using (`??=`) this default value" ��� instead of being tempted to use the *almost*-correct but subtly different-meaning ("if LHS is **falsy** , then...") alternative that we've all ended up using instead, `something || default`. And then having to "upgrade"/fix the logic to something more complicated/verbose when you inevitably realize that `false` values were inadvertently *also* using the logic path you intended only for `nil` values. As akim (Akim Demaille) summed up perfectly in #note-10: > > In practice when people use `||`, they [really] mean `??` It should be easier to do the right thing here, and *not* so easy (by virtue of it being the *only* obvious/easy solution provided by the syntax) to shoot yourself in the foot by inadvertently allowing `false` values to use the same logic path that you only *wanted* to be used for `nil`... If we *had* the syntax to allow it, it would be a lot easier / more common to allow `false` values as *distinct* values from `nil` ��� and allow them (without any extra effort) to arrive all the way inside your method/etc. instead of getting mistakenly lumped together with `nil` values (and accidentally triggering the "default value" path). As Michael Harrington [put it](https://github.com/kibiz0r/coalesce)... :) > Ruby, as a community, unfairly discriminates against `false` [...] > `false` is a perfectly non-nil object, and you're excluding it out of convenience! --- I would prefer spelling it `??` since that seems the most consistent with the existing `?.` operator, and seems like the most popular spelling (used by C#, JavaScript, PHP, PowerShell, and Swift). (`?:` as in [Kotlin](https://kotlinlang.org/docs/null-safety.html#elvis-operator) would be a fun spelling, but IMHO it look too much like the ternary operator `? :`, which of course is different since it checks for *truthy* values rather than *nullish* values, so that similarity could be surprising.) Shoot, even ***JavaScript*** has [had this operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing) since ECMAScript 2020. Are we really going to let JavaScript and PHP be more developer-friendly than Ruby on this point??? Say it ain't so. ---------------------------------------- Feature #13820: Add a nil coalescing operator https://bugs.ruby-lang.org/issues/13820#change-109694 * Author: williamn (William Newbery) * Status: Open ---------------------------------------- It would be nice if Ruby had an operator that only considered `nil` as false, like the null coalescing operators or "Logical Defined-Or operator" (Perl) found in some other languages. Ive seen things like `//` and `//=`m `??` and `??=`, or `?:` used for this. This would work like `||` and `||=` for short circuiting etc. except that only `nil` is considered a false condition. While Ruby considers only "false" and "nil" as false, with everything else true ("", [], {}, etc.) I still find occasionally people trip up when using logical or, `||` and `||=` when the value may be false. ```ruby a = 0 || 55 # = 0 Ruby already considers 0, "", etc. as true (oter languages do differ a lot here) a = 0 ?? 55 # = 0 So no change here a = nil || 55 # = 55, nil is false so right side is evaulated. a = nil ?? 55 # = 55, again no change a = false || 55 # = 55, however false is false for logical or a = false ?? 55 # = false, but its still a non-nil value ``` For example when doing things like: ```ruby def lazy @lazy ||= compute_this end def fetch(id, **opts) host = opts[:host] || default_host https = opts[:https] || true port = opts[:port] || (https ? 443 : 80) ... ``` Normally the intention is to use a default value or compute an action if no value is provided, which if the value may be false then requires special handling, or sometimes is missed and results in a bug. -- 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/