Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Immutable variables #23695

Closed
YeldhamDev opened this issue Nov 14, 2018 · 24 comments
Closed

Immutable variables #23695

YeldhamDev opened this issue Nov 14, 2018 · 24 comments

Comments

@YeldhamDev
Copy link
Member

YeldhamDev commented Nov 14, 2018

A middle term between a normal var, and a const, that once set, would remain forever with the given value. A good syntax could be using a word short as "var", like "let":

let var_name # Starts 'null', can still have something assigned to it.
let var_name = value # A value has been given, now its value cannot be changed anymore.

One of the main uses of immutable variables would be pairing it together with onready, when creating variables to keep stuff like nodes and certain references:
onready let var_name = $Node/SubNode

@ghost
Copy link

ghost commented Jan 10, 2019

#set once with whatever is in the inspector
export let var_name = 1.0

Though personally, I prefer val

@YeldhamDev
Copy link
Member Author

@somnivore val is too close to var, the syntax for something like this should be very different, so you can see it immediately and avoid silly mistakes.

@bojidar-bg
Copy link
Contributor

C# has it as readonly Type name, which can then be assigned only from the constructor. Maybe it can be an annotation (#20318)?

@blain1972
Copy link

what about using ref ?

@OvermindDL1
Copy link

@blain1972 Most languages that have a declaration of 'ref' use 'ref' as the mutable declaration where the default is immutable. Using it opposite in Godot sounds rife for confusion.

Most commonly let/val/const are used for immutable declarations among many languages, however those don't allow rebinding from an 'empty' state, most commonly such a thing would also be marked as lazy (such as let lazy blah = ...) with first access populating the value.

@DasAmpharos
Copy link

I am in favor of a let/val keyword. This is a pretty standard language feature. I know gdscript is similar to python, but protecting data is important, especially in use-cases like creating plugins where a developer might want to restrict a user from accessing something that could break functionality.

@Duroxxigar
Copy link
Contributor

I'm in favor of val as well.

@YeldhamDev var/val is used in Kotlin, no real issue.

@aaronfranke
Copy link
Member

aaronfranke commented Sep 3, 2019

C# has a keyword called readonly to do something similar. Despite the name, it can be written once, but only either inline (like const) or during constructors, so it's not write once from anywhere. Java's final keyword does the same thing.

val seems too close to var, and I don't like let personally. Aside from let, here's some ideas:

  • What if const thing with no value was allowed to be written once? I don't know if GDScript constants are evaluated compile-time like C# constants are (it doesn't say), but this could be an easy way to solve the problem with no additional keywords.

  • Re-use a keyword from another language, such as readonly or final.

  • Make it a modifier to var, such as writeonce var.

@raymoo
Copy link
Contributor

raymoo commented Sep 8, 2019

Why don't you like let? By "personally", do you mean that it's a personal dislike and it shouldn't affect whether it's chosen as the keyword?

@Calinou
Copy link
Member

Calinou commented Sep 8, 2019

I'm in favor of let, as it's harder to confuse compared to val (which looks close to var at a quick glance). Some languages like Nim already use let for immutable variables. However, there's the downside that JavaScript users may be confused by this keyword, since let variables are mutable there.

Edit: Swift also uses the let keyword for immutable variables (and var for mutable ones).

@Feniks-Gaming
Copy link
Contributor

I also support let it's hard to confuse it with anything else. It would also solve my issue of initiating some variables in parent class and allowing children to edit them This would allow for autocomplete of functions in parent class that use those variables and assign value to them in children only so the actual objects in the game that use them will have them working fine.

@katoneko
Copy link

katoneko commented Jan 5, 2020

Coming to GDScript after doing a coding session in Dart, which has a similar concept of final variables, I really miss them. lets or vals are really useful writing data classes that are often desired immutable. Would like to have immutable vars featured in GDScript as well!

@mnn
Copy link

mnn commented Jan 5, 2020

I programmed in Scala for quite some time and there are zero practical issues with var + val. If you try reassigning val compiler (IDE) will quickly tell you so. I find using let for constants unfortunate, because many people coming from JS/TS will find it confusing. Sure, there are languages like Haskell where it's used as an immutable binding, but let's be honest, how many people are coming from these significantly less popular languages?

Honestly, I find const in GDS confusing, because despite being it a dynamically typed language, it behaves like a macro or similar from "lower" statically typed languages. I would be for upgrading const to work same as const in JS - it can be filled at runtime (e.g. onready const a:= $A or const a:= A.new()), but cannot be re-assigned. Please note that its value is not necessarily immutable, only (I don't know how it's called in GDS) the reference/binding/pointer is.

@raymoo
Copy link
Contributor

raymoo commented Jan 30, 2020

The value is immutable. Godot has non-pointer (I don't like calling them references because it means something different in C++) types like int and float, where their values aren't pointers. It's just that for "array values" or "dict values" the value is a pointer, not the array or dict itself.

@ghost
Copy link

ghost commented Feb 21, 2020

What's the difference between let and const? They seem like they're supposed to accomplish the same thing (preventing modification of a variable's value once it's created), so I don't really understand why there'd be two keywords for them.

I speak from a position of very little programming experience, so sorry if this seems like a stupid question!

@YeldhamDev
Copy link
Member Author

@WARIO-MDMA const needs a value immediately when created. The idea is for let to allow giving it a value later, and then lock changes.

@ghost
Copy link

ghost commented Feb 21, 2020

@YeldhamDev I see. Thank you for clearing that up.

@Calinou
Copy link
Member

Calinou commented Feb 21, 2020

@YeldhamDev This may not necessarily be the case. We could still require let variables to be initialized on assignment, which should make the GDScript parsing logic significantly simpler.

@lboklin
Copy link

lboklin commented Feb 21, 2020

An immutable variable declared via let would have to be initialized immediately and then would never change within that scope. The difference from const is that it can be created within a scope at runtime. It's not constant (ie always the same value) - just immutable (ie it's not able to be reassigned after declaration).

@YeldhamDev
Copy link
Member Author

initialized on assignment

How would that work with the usage example I gave on the first post, about using it with onready?

@raymoo
Copy link
Contributor

raymoo commented Feb 27, 2020

It wouldn't work. Maybe modifying let with onready should be a special case that allows it to start as null and change, since it's clearly visible from the syntax to the user that it will be modified on ready (also easily enforceable because there's no separate assignment statement to check the correctness of).

I don't think it's too much of a problem UX-wise to allow later definition for other let declarations, since you can look at the declaration and tell that it may change from null because it is declared without a definition. It is however impossible at compile / semantic checking time to determine whether a variable will ever be assigned to multiple times. I think the feature will be much more useful for avoiding bugs if single assignment can be checked statically.

Maybe you could use static checks for lets with definition or with onready, and dynamic checks for let statements in function bodies with no definition, but this would create an inconsistency that might trip up users. It is possible also to try to conservatively detect safe situations with multiple assignment statements (for example, in separate branches of a conditional statement), but depending on how complex this criteria is, it might not be clear to users when it is allowed.

When GDScript becomes more performant it may also be a performance concern that you have to dynamically perform a null check, but at the moment it is not an issue because of the high overhead interpreting bytecode. Just make sure the dynamic check and the assignment are part of the same bytecode instruction so that you don't double that overhead.

@Calinou
Copy link
Member

Calinou commented May 11, 2020

Closing in favor of godotengine/godot-proposals#820, as feature proposals are now tracked in the Godot proposals repository.

@mnn

This comment has been minimized.

@Calinou

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests