godot icon indicating copy to clipboard operation
godot copied to clipboard

Add immutable/one-time assignable variables to GDScript (`let`)

Open Calinou opened this issue 4 years ago • 11 comments

Both local variables and member variables can be made immutable by using the let keyword instead of var during the declaration.

This can be used to write safer code in situations where const is not suited (as const is limited to constant expressions).

This let keyword behaves in a way similar to Nim's let keyword, Kotlin's val keyword and JavaScript's const keyword. The immutability is "flat" in the sense that the underlying data can still be modified (e.g. arrays and dictionaries can be modified, but not reassigned).

Immutable variables must also be initialized as soon as they're declared.

This feature is backwards-compatible with existing projects, which means it's possible to reimplement it for 3.x. I have a WIP branch here: https://github.com/Calinou/godot/tree/gdscript-add-immutable-variables-3.x

This closes https://github.com/godotengine/godot-proposals/issues/820.

TODO

  • [ ] Fix immutable variable checking for member immutable variables. There is some commented out code where I attempted this, but it didn't work because that part of the code was never called.
  • [ ] Decide what to do with setters. Should it be allowed to define a setter on a let property?

Preview

As you can see on the preview, it works for local variables but not member variables yet:

image

Calinou avatar Aug 26 '21 10:08 Calinou

Decide what to do with setters. Should it be allowed to define a setter on a let property?

Swift has a similar getter/setter syntax, and it forbids declaring getter/setter for let property.

I think this is reasonable because getter may return a different result for each call, and setter modifies the value. Neither fits the requirement of "immutable".

timothyqiu avatar Aug 26 '21 10:08 timothyqiu

I'm personally more partial to Kotlin's val, I think it makes more sense from an English standpoint. "Let x equal 2." doesn't specify whether or not x is readonly or not imo (in JS they're mutable, in F# they're mutable if you use the mut keyword). I like val more because it sounds like you're defining a value (and values aren't variable). I don't really care though, just my 2 cents.

AaronRecord avatar Aug 26 '21 14:08 AaronRecord

@LightningAA See the discussion in #23695.

YeldhamDev avatar Aug 26 '21 14:08 YeldhamDev

@Calinou BTW, does this work with @onready?

YeldhamDev avatar Aug 26 '21 14:08 YeldhamDev

@Calinou BTW, does this work with @onready?

It should work already, but member variables aren't properly immutable yet as per the PR description.

Calinou avatar Aug 26 '21 17:08 Calinou

What if we use const and let the engine optimize if it has its value in compilation time? let and const seems to do the same from the user perspective and would be good to have only 2 ways of declaring things

jcostello avatar Aug 27 '21 10:08 jcostello

What if we use const and let the engine optimize if it has its value in compilation time? let and const seems to do the same from the user perspective and would be good to have only 2 ways of declaring things

const provides additional assurance that the variable will never change based on external state, whereas let doesn't provide this guarantee. It's like constexpr vs const in C++. Due to this, I would prefer keeping the keywords separate.

Calinou avatar Aug 27 '21 12:08 Calinou

Only issue I see is a syntactic disparity between arguments and local/member variables.

Arguments become a special case where they are always mutable, and if let is being added with any performance reasons down the line (i.e. potential constant folding or pass-by-const-ref over value) then this means that arguments will always be an exception to the var/let dichotomy?

kayomn avatar Oct 18 '21 17:10 kayomn

val could be. Im still thinking that const as it works in JS should be consider.

jcostello avatar Mar 07 '23 19:03 jcostello

This should be discussed in the proposal (https://github.com/godotengine/godot-proposals/issues/820) to keep all comments in the same place.

vnen avatar Mar 07 '23 21:03 vnen

Also partial to using val as a the keyword over let. I am biased but many new programmers often start with JavaScript so having let be the equivalent of JSs const feels a bit weird accessibility wise

RyanCross avatar Mar 14 '23 20:03 RyanCross