[vim/vim] Vim9: cannot declare and assign to variable constant separately (Issue #9797)

65 views
Skip to first unread message

lacygoill

unread,
Feb 18, 2022, 8:50:47 AM2/18/22
to vim/vim, Subscribed

I was reading about const correctness via this comment, and thought about trying it in Vim9 script, but quickly realized that it was too annoying.

Suppose we have a variable whose value depends on some test:

vim9script
var n: number
if true
    n = 1
else
    n = 2
endif
echomsg n
1

Now, suppose we want to make sure the variable does not mutate. We can't use :const:

vim9script
const n: number
if true
    n = 1
else
    n = 2
endif
echomsg n
E1021: Const requires a value

Instead, we need :lockvar:

vim9script
var n: number
if true
    n = 1
else
    n = 2
endif
lockvar n
echomsg n
1

But if we allowed :const to not be followed by a value, the code would be easier to write (no need of :lockvar), and the intent would be easier to understand. Consider the fact that :lockvar could be written much later, and that while we're reading the code, as long as we don't find :lockvar, we are unaware that it's immutable.

Could we allow :const to be simply followed by a variable name and a type; then later lock the variable as soon as we assign to it some value?

FWIW, that's exactly what they seem to do in rust. Over there, variables are immutable by default. Which is why this code gives an error:

// written in /tmp/rs.rs
fn main() {
    let x;
    {
        x = 1;
        x = x + 2;
    }
    println!("x is: {:?}", x);
}
$ mkdir -p /tmp/build && rustc --out-dir /tmp/build/ /tmp/rs.rs && /tmp/build/rs
error[E0384]: cannot assign twice to immutable variable `x`
 --> /tmp/rs.rs:5:9
  |
2 |     let x;
  |         - help: consider making this binding mutable: `mut x`
3 |     {
4 |         x = 1;
  |         ----- first assignment to `x`
5 |         x = x + 2;
  |         ^^^^^^^^^ cannot assign twice to immutable variable

error: aborting due to previous error

For more information about this error, try `rustc --explain E0384`.

But they can still separate the declaration from the assignment:

// written in /tmp/rs.rs
fn main() {
    let x;
    {
        x = 1;
    }
    println!("x is: {:?}", x);
}
$ mkdir -p /tmp/build && rustc --out-dir /tmp/build/ /tmp/rs.rs && /tmp/build/rs
x is: 1


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9797@github.com>

bfrg

unread,
Feb 18, 2022, 9:32:38 AM2/18/22
to vim/vim, Subscribed

You can always do something like this:

const n: number = Is_true() ? Set_value(1) : Set_value(2)

And the complex logic is hidden inside the three functions. This also makes the code more readable.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

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

lacygoill

unread,
Feb 18, 2022, 9:44:30 AM2/18/22
to vim/vim, Subscribed

That's a nice workaround. I'll keep it in mind. But we still need to create at least one or two intermediate functions (here Is_true() and Set_value()). It would be nice for the Vim9 syntax to let us separate the declaration from the assignment.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

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

Bram Moolenaar

unread,
Feb 18, 2022, 10:19:39 AM2/18/22
to vim/vim, Subscribed

Rust is not a good example, it makes things more difficult (with the excuse that it's safer).

You should compute the value first, then declare the const:

vim9script
var val: number
if condition
    val = 1
else
    val = 2
endif
const n = val

It does require an extra temporary variable, but the big advantage is that it's clear where the constant is set and
there can be no mistakes with that.

If we would allow first declaring the constant without a value, and then later set the value, this can get very complicated if it's not a simple if-then-else. Also, setting the value can come much later, there could be a try/catch in between, etc.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

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

lacygoill

unread,
Feb 18, 2022, 10:23:04 AM2/18/22
to vim/vim, Subscribed

That's fair. I didn't think of all the implications. Closing the issue then.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

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

lacygoill

unread,
Feb 18, 2022, 10:23:08 AM2/18/22
to vim/vim, Subscribed

Closed #9797.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/9797/issue_event/6100064638@github.com>

Reply all
Reply to author
Forward
0 new messages