<p>Many languages extend their &quot;indexing&quot; operator <code>.</code> to a nil-coalescing variant <code>?.</code> to deal with indexing chains such as <code>a.b.c</code> where the parents are optional, which can then be conveniently rewritten as <code>a?.b?.c</code>. This seems to be the main use case for nil-coalescing besides providing a default if something is <code>nil</code>, e.g. <code>x ?? 42</code> (I'm using the Lua term <code>nil</code> rather than <code>null</code> here since I plan to extend Lua).</p>
<p>I'm considering generalizing this: All binary operators should support nil coalescion for <em>both operands</em> by putting a question mark on their respective sides. For example, you could write <code>t?.x</code> if <code>t</code> may be <code>nil</code> to short-circuit the expression to <code>nil</code>. <code>t.?x</code> on the other hand would short-circuit to <code>nil</code> if <code>x</code> is <code>nil</code> (this is not really necessary though since <code>t[nil]</code> is <code>nil</code> in Lua, given no metamethods).</p>
<p>This seems to be useful for arithmetic operations (e.g. <code>c = a ?+? b</code> could come in handy) and I would prefer not to impose arbitrary restrictions on which operators nil-coalesce. Relational operators could also benefit.</p>
<p>It is however pretty useless if not detrimental for the logic operators <code>not</code>, <code>and</code> and <code>or</code>: <code>not? nil</code> would evaluate to <code>nil</code>, which would be rather confusing, since we get a conflict between nil-coalescing operators short-circuiting and logic operators short-circuiting as well as conflicting behavior: <code>nil ?or 1</code> would evaluate to <code>nil</code>, behaving like <code>and</code> rather than <code>or</code>.</p>
<p>(In a Lua extension), should nil-coalescing be restricted to indexing (and the &quot;default&quot; operator <code>??</code>), where it is most useful? Which limits should be imposed on a generalization?</p>

<syntax><language-design><operators><syntactic-sugar>
Pros and cons of generalized `nil`-coalescing operators
CC BY-SA 4.0
2023-07-06T12:37:22.783Z
I've usually heard `?.` referred to as optional-*chaining*, and only `??` is *coalescing*.
Bbrk24
CC BY-SA 4.0
2023-07-06T12:43:21.027Z
@Bbrk24 indeed it seems I have been using the word "coalescing" wrong. The `[?]<op>[?]` operators are supposed to be `nil`-short-circuiting rather than "coalescing"...
Luatic
<p>I think the best argument against such operators is that they would make control-flow harder to read, due to short-circuiting.</p>
<p>An optional chaining operator like Javascript's is <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining#short-circuiting" rel="nofollow noreferrer">short-circuiting</a>, meaning that if the left operand is nil, the rest of the expression is not evaluated. For example, in <code>obj?.x.y</code>, the property access <code>.y</code> won't be evaluated if <code>obj</code> is nullish. This makes sense for property access, because of course you wouldn't want to evaluate <code>nil.y</code> in the case where you <em>know</em> the left operand is nil. It's also relatively readable, because property accesses have a very high precedence and few ways for the expression to continue; and <code>obj?.x?.y</code> would have a different meaning, since it doesn't fail if <code>obj</code> is non-nil but <code>obj.x</code> is nil.</p>
<p>But for an operator like <code>+</code> or <code>-</code> with a much lower precedence, the same rule could have surprising consequences:</p>
<pre class="lang-lua prettyprint-override"><code>let result1 = a ?- b + c()
let result2 = if a ?&gt; 0 then d() else e() end
</code></pre>
<p><sub>(Yes, Lua doesn't have ternary expressions, but other languages do.)</sub></p>
<p>In the above example, it would be quite surprising if <code>c()</code> were evaluated when <code>a</code> is nil, because it is &quot;clearly&quot; part of the rest of the expression, even though it is not a descendant of the <code>?-</code> node in the parse tree. On the other hand, it would be very surprising if neither <code>d()</code> nor <code>e()</code> were evaluated when <code>a</code> is nil, even though a similar logic applies.</p>
<p>All of this said, you could say that operators like <code>?+</code> or <code>?+?</code> which coalesce on the left operand aren't short-circuiting, but then either this would be inconsistent with the rule for <code>?.</code>, or you would have to forego short-circuiting entirely in which case your <code>?.</code> operator would have different behaviour to what users are familiar with from other languages.</p>
<hr />
<p>One more reason to not have operators like <code>?+?</code> is that they are hard to search for. Operators like this will be rarely used, so they will often be encountered by users who haven't seen them before. But existing search engines like Google or Stack Overflow's search don't do a good job of searching for punctuation like this.</p>

CC BY-SA 4.0
2023-07-06T12:18:17.943Z
2023-07-06T12:18:17.943Z
kaya3
<p>This could be done better using exceptions. You could define an operator to catch nil exceptions non-recursively and return another value instead, possibly the nil value, possibly in a grammar similar to <code>@</code> in PHP.</p>

CC BY-SA 4.0
2023-07-07T04:42:11.243Z
2023-07-07T04:42:11.243Z
user23013
<h2>Cons</h2>
<p>Adding symbols to transform operators is a rare practice, as far as I know another one is julia, which appends <code>.</code>.</p>
<p>It might look like this if extended down the road:</p>
<ul>
<li><code>a + b</code>: add</li>
<li><code>a .+ b</code>: broadcast add</li>
<li><code>a ?.+ b</code>: nullable broadcast add</li>
<li><code>a ?.+= b</code>: nullable broadcast add assign</li>
<li>......: some more horrible add</li>
</ul>
<h2>Syntax Sugar with Metatable Extension</h2>
<p>In fact I think your definition is not &quot;generalized&quot; enough, I call this <code>monadic call syntax</code>.</p>
<p>When the value of the operation is a monad such as <code>Option&lt;T&gt;</code>, <code>Result&lt;T,  E&gt;</code>, <code>ParseState&lt;R&gt;</code>, etc.</p>
<p><code>?</code> means <code>and_then</code>, such as:</p>
<pre class="lang-lua prettyprint-override"><code>object?:invoke()
-- object:and_then(function(inner) return inner.invoke() end)

object?[index]
-- object.and_then(function(inner) return inner[index] end)

object ?= new
-- object.and_then(function(inner) inner = new end)
</code></pre>
<p><code>??</code> means <code>or_else</code>, such as:</p>
<pre class="lang-lua prettyprint-override"><code>object ?? default
-- object:or_else(function() return default end)
</code></pre>
<p>Of course lua does not have generics, I think you can add <code>__and_then</code> and <code>__or_else</code> in the metatable as a duck type interface.</p>
<hr />
<p>I prefer <code>a! or b</code> to <code>a ?or b</code>, where <code>!</code> means <code>assert non-nil</code>, maybe you can add <code>__assert</code> as duck type interface.</p>
<p>In general it's up to you, supporting <code>a ?- b</code>, <code>?- a</code>, <code>a ?~= b</code> etc. doesn't make much difference in implementation.</p>
<p>And I think this method is more suitable for converting your extension language to the standard lua language.</p>

CC BY-SA 4.0
2023-07-06T11:42:37.250Z
2023-07-06T11:57:30.517Z
2023-07-06T11:57:30.517Z
Aster
CC BY-SA 4.0
2023-07-06T12:10:41.023Z
I had not considered extending this to assignment (which is a statement in Lua, though I'm considering changing that); I would of course extend it to also support calls and indexing operations, though I probably wouldn't add new metamethods. I wasn't aware of broadcast add either. Assignment operators will be a follow up question :)
Luatic
CC BY-SA 4.0
2023-07-06T12:38:39.317Z
Your "and-then" assignment does exist in Swift, but the spacing is different: `object? = new`.
Bbrk24
CC BY-SA 4.0
2023-07-06T12:45:20.323Z
@Bbrk24 I suddenly remembered that swift also have combined operators, `&+` indicates overflow add.
Aster
CC BY-SA 4.0
2023-07-07T00:55:49.553Z
That mom said call syntax is very interesting, I just might use it in my language 
Seggan
# Pros and cons of generalized `nil`-coalescing operators
Posted by: username_0 on 2023-07-06
Many languages extend their "indexing" operator `.` to a nil-coalescing variant `?.` to deal with indexing chains such as `a.b.c` where the parents are optional, which can then be conveniently rewritten as `a?.b?.c`. This seems to be the main use case for nil-coalescing besides providing a default if something is `nil`, e.g. `x ?? 42` (I'm using the Lua term `nil` rather than `null` here since I plan to extend Lua).

I'm considering generalizing this: All binary operators should support nil coalescion for *both operands* by putting a question mark on their respective sides. For example, you could write `t?.x` if `t` may be `nil` to short-circuit the expression to `nil`. `t.?x` on the other hand would short-circuit to `nil` if `x` is `nil` (this is not really necessary though since `t[nil]` is `nil` in Lua, given no metamethods).

This seems to be useful for arithmetic operations (e.g. `c = a ?+? b` could come in handy) and I would prefer not to impose arbitrary restrictions on which operators nil-coalesce. Relational operators could also benefit.

It is however pretty useless if not detrimental for the logic operators `not`, `and` and `or`: `not? nil` would evaluate to `nil`, which would be rather confusing, since we get a conflict between nil-coalescing operators short-circuiting and logic operators short-circuiting as well as conflicting behavior: `nil ?or 1` would evaluate to `nil`, behaving like `and` rather than `or`.

(In a Lua extension), should nil-coalescing be restricted to indexing (and the "default" operator `??`), where it is most useful? Which limits should be imposed on a generalization?
**Tags:** syntax language-design operators syntactic-sugar
> **Comments:**
> **username_1**: I've usually heard `?.` referred to as optional-*chaining*, and only `??` is *coalescing*.  
> **username_0**: @Bbrk24 indeed it seems I have been using the word "coalescing" wrong. The `[?]<op>[?]` operators are supposed to be `nil`-short-circuiting rather than "coalescing"...  
---
## 3 answers
### Answer by username_4 on 2023-07-06. Score: 3
Cons
Adding symbols to transform operators is a rare practice, as far as I know another one is julia, which appends ..
It might look like this if extended down the road:

a + b: add
a .+ b: broadcast add
a ?.+ b: nullable broadcast add
a ?.+= b: nullable broadcast add assign
......: some more horrible add

Syntax Sugar with Metatable Extension
In fact I think your definition is not "generalized" enough, I call this monadic call syntax.
When the value of the operation is a monad such as Option, Result, ParseState, etc.
? means and_then, such as:
object?:invoke()
-- object:and_then(function(inner) return inner.invoke() end)

object?[index]
-- object.and_then(function(inner) return inner[index] end)

object ?= new
-- object.and_then(function(inner) inner = new end)

?? means or_else, such as:
object ?? default
-- object:or_else(function() return default end)

Of course lua does not have generics, I think you can add __and_then and __or_else in the metatable as a duck type interface.

I prefer a! or b to a ?or b, where ! means assert non-nil, maybe you can add __assert as duck type interface.
In general it's up to you, supporting a ?- b, ?- a, a ?~= b etc. doesn't make much difference in implementation.
And I think this method is more suitable for converting your extension language to the standard lua language.
> **Comments:**
> **username_0** (2023-07-06): I had not considered extending this to assignment (which is a statement in Lua, though I'm considering changing that); I would of course extend it to also support calls and indexing operations, though I probably wouldn't add new metamethods. I wasn't aware of broadcast add either. Assignment operators will be a follow up question :)  
> **username_1** (2023-07-06): Your "and-then" assignment does exist in Swift, but the spacing is different: `object? = new`.  
> **username_4** (2023-07-06): @Bbrk24 I suddenly remembered that swift also have combined operators, `&+` indicates overflow add.  
> **username_5** (2023-07-07): That mom said call syntax is very interesting, I just might use it in my language   
---
### Answer by username_2 on 2023-07-06. Score: 2
I think the best argument against such operators is that they would make control-flow harder to read, due to short-circuiting.
An optional chaining operator like Javascript's is short-circuiting, meaning that if the left operand is nil, the rest of the expression is not evaluated. For example, in obj?.x.y, the property access .y won't be evaluated if obj is nullish. This makes sense for property access, because of course you wouldn't want to evaluate nil.y in the case where you know the left operand is nil. It's also relatively readable, because property accesses have a very high precedence and few ways for the expression to continue; and obj?.x?.y would have a different meaning, since it doesn't fail if obj is non-nil but obj.x is nil.
But for an operator like + or - with a much lower precedence, the same rule could have surprising consequences:
let result1 = a ?- b + c()
let result2 = if a ?> 0 then d() else e() end

(Yes, Lua doesn't have ternary expressions, but other languages do.)
In the above example, it would be quite surprising if c() were evaluated when a is nil, because it is "clearly" part of the rest of the expression, even though it is not a descendant of the ?- node in the parse tree. On the other hand, it would be very surprising if neither d() nor e() were evaluated when a is nil, even though a similar logic applies.
All of this said, you could say that operators like ?+ or ?+? which coalesce on the left operand aren't short-circuiting, but then either this would be inconsistent with the rule for ?., or you would have to forego short-circuiting entirely in which case your ?. operator would have different behaviour to what users are familiar with from other languages.

One more reason to not have operators like ?+? is that they are hard to search for. Operators like this will be rarely used, so they will often be encountered by users who haven't seen them before. But existing search engines like Google or Stack Overflow's search don't do a good job of searching for punctuation like this.
---
### Answer by username_3 on 2023-07-07. Score: 1
This could be done better using exceptions. You could define an operator to catch nil exceptions non-recursively and return another value instead, possibly the nil value, possibly in a grammar similar to `@` in PHP.
---
