[vim/vim] null coalescing operator assignment (foo ??= bar) (Issue #10343)

60 views
Skip to first unread message

nicholas a. evans

unread,
May 2, 2022, 6:03:24 PM5/2/22
to vim/vim, Subscribed

First, thanks for adding the null coalescing operator! I know 8.2.1794 was a year and a half ago, but I haven't been keep closely up-to-date with new features and I only just discovered it today. 😄

It's not difficult to work around the absence of this feature. But it seems like an inconsistency or an oversight, since most other similar operators have an assignment version.

let foo = foo ? foo : bar  " what I used to do

let foo = foo ?? bar       " what I'm doing now

let foo ??= bar            " what I'd like to do

Running that last line on v8.2.4842 gives the following message:

E15: Invalid expression: "??= "bar""

I personally find falsy-coalescing-assignment both easier to read and less likely to contain typos than those other more repetitive versions.

Thanks!


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343@github.com>

Bram Moolenaar

unread,
May 2, 2022, 6:56:58 PM5/2/22
to vim/vim, Subscribed

What other languages have a similar assignment operator?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343/1115445956@github.com>

Nick Jensen

unread,
May 2, 2022, 7:11:14 PM5/2/22
to vim/vim, Subscribed

C# has it: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343/1115453811@github.com>

Doug Kearns

unread,
May 3, 2022, 5:50:57 AM5/3/22
to vim/vim, Subscribed

What other languages have a similar assignment operator?

OTTOMH, Dart, JavaScript, PowerShell and PHP.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343/1115918146@github.com>

nicholas a. evans

unread,
May 3, 2022, 1:10:10 PM5/3/22
to vim/vim, Subscribed

Yeah, I think it's a recent(-ish... since 2019?) addition to Javascript, C#, and PHP. One important distinction: their ?? and ??= operators evaluate the rhs only when the lhs is null or undefined.

IMO, the docs should be updated to reflect this difference. Perhaps something like the following?

- This is also known as the "null coalescing operator" but that's too

- complicated, thus we just call it the falsy operator.

+ This is similar to the "null coalescing operator" found in Javascript or C# or

+ PHP, except that it uses falsiness instead of null or undefined, thus we call it

+ the falsy operator.

Behaving less like a null coalescing operator and more similarly to vim's falsy-operator:

  • Python's a or b. But Python doesn't have any sort of or operator, as far as I know. 🙁
  • Perl's a || b. I'm not looking it up now, but I'm pretty sure Perl had ||= when I first tinkered with it, ~1998.
  • Ruby added ||= in 1999. Ruby is my primary language.

It's worth noting that ruby's notion of "falsy" is much more restrictive than vim's: nil and false are falsy and everything else is truthy. Idiomatic ruby uses ||= ubiquitously for setting variable with defaults and for simple memoization of method results. The ||= operator isn't as useful when we need to distinguish between nil, false, and undefined, but most of the time it's very nice to use.

Before I knew about the ?? falsy operator, the top of my .vimrc contained:

if empty($XDG_CONFIG_HOME) | let $XDG_CONFIG_HOME=$HOME..'/.config'      | endif

if empty($XDG_DATA_HOME)   | let $XDG_DATA_HOME  =$HOME..'/.local/share' | endif

After I learned about ??, I updated it to:

let $XDG_CONFIG_HOME = $XDG_CONFIG_HOME ?? $HOME.."/.config"

let $XDG_DATA_HOME   = $XDG_DATA_HOME   ?? $HOME.."/.local/share"

And with ??= I'd be able to use:

let $XDG_CONFIG_HOME ??= $HOME.."/.config"

let $XDG_DATA_HOME   ??= $HOME.."/.local/share"

IMO that last one isn't just less typing; it's also easier to quickly read/understand when quickly scanning through the code.. Like I said up top, it's not difficult to work around the absence of this feature. But it sure is nice to use when I have it. Thanks for your consideration!


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343/1116341621@github.com>

Shane-XB-Qian

unread,
May 9, 2022, 12:11:42 PM5/9/22
to vim/vim, Subscribed

looks golang had no such thing.. :-)
// which by if/else maybe more explicit..
or if had to be, then maybe simply just ?= was better?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343/1121299351@github.com>

nicholas a. evans

unread,
Jul 25, 2022, 11:06:41 AM7/25/22
to vim/vim, Subscribed

I was just reminded of this ticket and wanted to share a detail that I left out in the description. The implementation of ??= should be subtly different from other operator= assignments, which convert a op= b into a = a op b. Instead, a ??= b should translate to something more like a ?? (a = b).

To quote from ruby's assignment syntax documentation:

There are also ||= and &&=. The former makes an assignment if the value was nil or false while the latter makes an assignment if the value was not nil or false.

Here is an example:

a ||= 0
a &&= 1

p a # prints 1

Note that these two operators behave more like a || a = 0 than a = a || 0.

And MDN's description of Javascript's nullish assignment operator makes the same point:

Logical nullish assignment short-circuits as well meaning that x ??= y is equivalent to:

x ?? (x = y);

And not equivalent to the following which would always perform an assignment:

x = x ?? y;


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/10343/1194172839@github.com>

Reply all
Reply to author
Forward
0 new messages