godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.9k stars 21.04k forks source link

GDScript parse error for const inside functions #35856

Open dino- opened 4 years ago

dino- commented 4 years ago

Godot version:

Godot 3.2

OS/device including version:

Arch Linux, x86_64

Issue description:

Constant declarations aren't being allowed inside functions. I feel like we should be encouraging people to use immutable data where possible and this is preventing that. What you see is the misplaced: const error in the script editor.

This seems similar to #8315 with the difference being that one was in script/file scope, not function scope.

Steps to reproduce:

Define a const in any function.

gdscript-func-const-bug

Calinou commented 4 years ago

Duplicate of #23695.

dino- commented 4 years ago

After reading #23695, I don't see how this is the same issue. The const keyword just plain doesn't work inside functions. Can @Calinou or anyone explain further? Thanks.

Calinou commented 4 years ago

@dino- This is not a bug, it's an unimplemented feature :slightly_smiling_face:

Adding support for immutable variables isn't trivial. Also, note that const outside of functions is designed to create "real" constants, not just immutable variables (only constant expressions are allowed).

We can look at improving the error message when attempting to use const in a function, though.

akien-mga commented 4 years ago

I think the error message should be made clearer so that users understand that constants can only be defined in the outer scope.

ghost commented 4 years ago

@Calinou What's the difference between a "real" constant and an immutable variable? Sorry if that's a dumb question, but I'm trying to follow the conversation in https://github.com/godotengine/godot/issues/23695 and am having a hard time understanding what it's about.

Calinou commented 4 years ago

@WARIO-MDMA A "real" constant is evaluated at compile-time* and must be a constant expression. This means you can only assign literal expressions (2 + 2) or simple, deterministic functions like sin(2) to a real constant. You definitely can't do things like assigning a random number to it, as the value would be different if you compile the script again. In C++, this would be equivalent to a variable declared using the constexpr specifier. Compile-time constants can also result in better performance, as the compiler can guarantee the expression will only be evaluated once.

An immutable variable behaves exactly like a variable, except you're not allowed to assign it again. Typically, you must also initialize the variable immediately upon declaration (unlike a mutable variable). This is equivalent to the JavaScript const keyword. In many languages including JavaScript, constants are shallow. You can still add/remove items from a const array as long as you don't re-assign it fully:

const someArray = [1, 2, 3];

// Valid. We're not reassigning the variable, we're only adding a value to the underlying array.
someArray.push(4);

// Invalid (we're reassigning the variable).
someArray = [1, 2, 3, 4];

This doesn't provide as much safety as compile-time constants, but is still safer than mutable variables. Modern language practices recommend using immutable variables whenever possible, as it makes the code's intent easier to understand.

*: In interpreted languages like GDScript, "compile-time" refers to the moment the script is parsed and interpreted.

ghost commented 4 years ago

@Calinou Thank you for the explanation! If immutable variables are implemented in GDScript, the difference between them and const variables should be clearly documented somewhere. Perhaps it's just my inexperience talking, but I feel like there will be a lot of people who won't understand the difference otherwise.

vnen commented 4 months ago

This is already supported in Godot 4.x, not sure if should add support in the 3.x line as well. We can probably add a better message though.