The following is solely in the context of `Untyped Declaration` set to Error.
As in a globally enforced strict typing type of project, with no mixed/partial typing allowed.
The design decision to enforce void with static typing bloats the code.
There is only a single compiler setting Untyped Declaration that controls whether any untyped decl it’s an error or not. I guess that it must be related to how compiler resolves if the function is static/dynamic, and it may be an ambiguity when parameters are typed and return isn’t, but there must be a special case for void return.
From user perspective there is no reason to type out -> void: because it can be inferred.
For me, at least, it means I can look at a function and know immediately if it is intending to return something or not. I do get the point that if there is not a ->int or something you could infer it returns nothing. For me I like the design choice. For the engine I am pretty sure it just helps with clarity on reporting an error or warning, I doubt it has much impact on performance. As you said, it was a design decision. Personally I am in favour of it. (Without it, did it mean to return something and I have forgotten to add it, or does it not mean to return anything?) I prefer my interpretation of code to not rely on inferences as much as possible.
I like clarity as well, but a bit different - if I set the project and I expect it to be fully statically typed, I expect the rules to be consistent.
Without it, did it mean to return something and I have forgotten to add it, or does it not mean to return anything?
Without it, if the static typing is enforced by compiler, the function return type should be void.
There is no ambiguity, if you can consistently rely on no return specification == void return, then thats it. There should be no more variants to it. Adding return 0 to such function would result in parsing error.
It helps clarity that if you consistently skip -> void it helps legibility, because now functions that actually return anything stick out.
I am not arguing against your style, I am arguing in favor of an option that supports mine.
Yeah, I have to admit what you say makes some sense. It being enforced that no defined return type means ->void always would work.
I would not object and be open to trying it. I do like the idea that when scanning a long list of functions, the returns stick out a bit. I think that might well help legibility. I think it would resonate better with new coders too.
Well, if it ever changes, I would be happy to run with it. I do like the idea of minimalist boiler plate.
What you are proposing is that if you turn on warnings or errors for strict typing, it not call you out for it. You can accomplish this now by not turning it on, policing yourself and not using autocomplete (which adds -> void: on the end of functions).
If you actually want this feature, you should be making the proposal in the GitHub proposals section, not here.
To me, strict typing means strict typing. Not partial strict typing.
What you are suggesting increases cognitive load on the developer. It does not really bloat code to any appreciable amount. (Every ~114 times you use it, it adds 1k to your program size - which is less than almost any single image or model your game is using.) It has no detrimental effect on performance.
I must disagree and I think you are objectively wrong. First - strict typing means that types are not dynamic. That’s it. It doesn’t mean what you think it means.
c++ auto or c# var are still part of the strictly/strongly typed languages, they are resolved at compile time and are syntactic sugar which main purpose is to reduce verbosity of the language.
In GDScript := serves the same function, infers the type on assignment. It’s part of strict typing and its existence already invalidates your argument.
Inferring void return is also just syntactic sugar. It would not bypass strict typing, the return type would still resolve to void.
First, c++ and c# are strongly typed languages. They cannot produce ambiguities between typed and non typed things. So introducing this into the discussion is mixing apples and oranges.
Second, walrus is a shorthand for explicit type declaration. It will not tolerate any switching between typed and untyped expressions. Which is precisely what you propose - for language to tolerate this. What you want is exactly like wanting for walrus to just make the variable untyped if it cannot infer the type of the assigned expression.
You seem to be forgetting one important thing. Return type declaration is not only for calling code type safety. It’s for function implementation code type safety as well. If I need to implement a void function and my implementation accidentally tried to return some value, your proposed behavior will betray the type safety principle here. It will switch between static/duck typing willy-nilly, caused by type mistakes in the function implementation. Very bad thing from type safety perspective.
On top of this. Why make an exception for void return type? If you claim that the return type should be automatically enforced if it could be inferred, then why not do it for any type:
func foo():
return 1
Should then implicitly be typed as:
func foo() -> int:
return 1
…because the type can be unambiguously inferred here. Sounds a bit silly when we put it like that, doesn’t it? But this is precisely what you propose.
Not aware of dynamic in c++ but c# has dynamic, with the same set of issues here.
Correct it is syntactic sugar.
Incorrect, i propose for lack of return type to resolve to void , which in your example will invariably produce an error on any return from the function.
Same as the above, it is not what I am proposing. I am proposing for it to be only void. Any return would produce an error, which is fully inline with strict typing. For the compiler void would be equivalent to no specification.
This is not what I am proposing. I am proposing a logical assumption in the context of strict typing.
Inferred arbitrary type is dangerous and goes against strict typing. That is why the only assumption I think is safe to make to reduce code verbosity is void that’s it.
You must declare an initialization expression at the time you declare a C++ auto variable.
C#
var count = 10;
You must declare an initialization expression at the time you declare a C# var variable.
GDScript
var count
var count2 = 10
var count3: Variant = 10
var count4: int
var count5: int = 10
var count6 := 10
You may declare an initialization expression at the time you declare a GDScript variable. But in GDScript it is still of type Variant. In fact, until we get to variable #4, they’re all type Variant. So you cannot really compare C++ and C# to GDScript, because they do not have a Variant type.
Because GDScript is a Statically and Dynamically Typed Language. The enforcing of strict typing is applied on top of that.
With enabled strict typing compiler warning your first variable decl already produces an error.
I am talking about and in context of enforced strict typing with Untyped Declaration set to Error.
Then you’ll need a keyword to declare a function to be duck typed, so you’re back at the same overall level of verbosity, just from the other side. If your counterargument here is that no duck typing should be allowed whatsoever, then what you really arguing for is to make GDScript into a 100% strongly typed language, which imo would severely cripple its convenience.
Incorrect, I propose a syntactic sugar feature that is limited, safe and reduces verbosity.
I propose that it is implemented as an additional, global warning/compiler flag.
No keyword required, upon enabling such option, parser would assume lack of return type == void globally. Currently there is only a single flag that governs this, and it does not discriminate cases where relaxations can be made because it is safe to assume something.
How is that any different from func foo() -> void:? It even has more characters. You just changed what absence defaults to. By what metric would one needed to be preferred over the other?