Until recently I thought that using self.my_var to ensure the use of setters/getters was something I only had to pay attention to inside the class's file, but it turns out that's not the case. I also need to think about it in subclasses, which I did not expect. That means a lot more mental tracking to do to remember which variables I need to prefix with self. and when, and which I don't; and potentially more bugs.
GDScript does not demand the use of self. in front of member variables so I only use it when I need to, but that very error prone and a little inconsistent.
In the changes leading to 3.0, GDScript has been moving away from explicit use of setter and getter functions and towards "property access as default", which is explicited here. Those properties still use setters and getters but do not require self. to do so, making my properties behave unlike those provided by Godot. My feeling is that this goes against the spirit of simplification/better defaults described throughout that blog post ("$" syntax, automatic callbacks, etc.).
I would like to consider reversing the logic: use setters and getters by default and use a special syntax to bypass them. E.g.:
var foo setget set_foo
func set_foo(new_foo):
.foo = new_foo
.foo is the same syntax used to call a function in a base class.
Syntax bickering aside, I believe shifting to "use setters/getters by default" would make GDScript less error prone, more consistent and easier to use.
Sounds like a good addition to me, I never liked the self syntax myself.. 馃槂
I am against this for a few reasons.
1) VM simplicity: Internal access goes via a separate path (access is O(1) ). Doing this means having to do a lot more checks regarding the access type.
2) Consistency: I think it's clear that internal access is meant to be one thing, and setget is for external access.
Also at this point, doing a change like this is too much, we are pretty much feature frozen, and need to release a new version asap. The list of things to fix is pretty big already.
@reduz definitely not expecting this for 3.0
One example: using setget on foo to systematically emit("foo_changed"). Having to remember that foo must alway use self.foo unlike other properties feels like an unnecessary mental charge. Very error prone. Especially if you do it from a sub-(sub-)*class. Also if you add that after you coded everything, you need to edit all your scripts.
I understand you point about the VM. :/
I'm not sure that the internal/external distinction is very clear from the language perspective or that setget should align with it, especially since there's no notion of privacy whatsoever. This feels like a case of implementation leaking through the language abstraction to me.
Now, I'm wildly speculating here, but how about a 'property' variable?
# property var ...
# prop var ...
property some_prop setget set_someprop
func set_someprop(prop):
# etc...
Accesses of some_prop goes through setget first, and if not found access the variable directly.
I'm not privy to the VM internals, but I think this could be implemented in the same way as properties from the C++ side in Godot 3.
The extra syntax is fairly worth it, as the number of variables you use this on is naturally low.
Could this technically be solved by adding a pass on the gdscript IR that translates reading/writing to variables with setters/getters to equivalent of self.foo? We shouldn't need to touch the VM and keep direct access to other variables.
The property solution is also fine by me. C#/F# users are used to that.
I agree that the current implementation is confusing and non-beginner friendly.
I found the fact that internal setting and getting from inside the script doesn't actually use the setgets more than a month ago because I was having some bugs, and then I thought maybe I am just dumb.
But then, 3 days ago, a friend had a bug specifically with that same fact, and he decided to remove any use of getseters of his project because it was too easy to shot yourself in the foot.
And then today another friend told me that he has been struggling with a bug for a week, and it was ALSO because of that same fact.
In conclusion, that specific part of gdscipt is confusing, especially for Godot beginners.
Edit: I propose this change should target version 3.2
My opionnion/experience: If you first stumble across this feature, you think to yourself: "Hey, that's great! It automatically calls the setter and getter functions when I use the variable?" only to find out that it doesn't, and that you still have to use self. for it to work.
Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.
The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.
If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!
Most helpful comment
I agree that the current implementation is confusing and non-beginner friendly.
I found the fact that internal setting and getting from inside the script doesn't actually use the setgets more than a month ago because I was having some bugs, and then I thought maybe I am just dumb.
But then, 3 days ago, a friend had a bug specifically with that same fact, and he decided to remove any use of getseters of his project because it was too easy to shot yourself in the foot.
And then today another friend told me that he has been struggling with a bug for a week, and it was ALSO because of that same fact.
In conclusion, that specific part of gdscipt is confusing, especially for Godot beginners.
Edit: I propose this change should target version 3.2