-
Notifications
You must be signed in to change notification settings - Fork 207
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
Should primary constructors for structs use named parameters, positional parameters, or allow either? #2365
Comments
Constructor parameter lists are more complicated than field declarations, and users want to have complete control over whether things are named or not, and in which order they occur. Fields are trivial in comparison. Because of that I'd make the declaration a parameter list, allowing the user to get that control: struct Foo(int x, {int y = 4}) {
...
} Then that will introduce:
If we allow extending other structs, the parameter list can also contain Default values will have to be constant. If we want to have non-constant default values, we could:
|
+1. I've spent a bunch of time investigating primary constructors (specify the parameters and get the fields for free) and enhanced default constructors (specify the fields and get the parameters for free) and my general conclusion is that parameters contain more configured options than fields, so inferring fields from parameters is less lossy than trying to infer parameters from fields. Parameters have:
Fields have:
It would be fairly straightforward to allow On the other hand, I think field declarations visually scale better when you have many of them and they have doc comments and/or metadata annotations.
+1. |
The one issue that I see with saying that these are parameter lists is that I see value in having |
I think I'm slightly more worried about changing the name of the constructor parameter (if case you want the field to be private, and the parameter to be named). That actually means that what you write as a parameter list, is not the parameter list you get. Adding |
These topics have been mentioned several times above, but let me refer to the latest comments: @lrhn wrote:
Right, that modifier has no effect on a getter, and struct instance variables do not have setters. I think it is definitely not needed in a struct.
In this case I don't quite agree. We could allow late final instance variables (with or without an initializer) to be declared in the normal style (in the class body), as long as there are no generative constant constructors. The late final instance variable with an initializer would work just like a getter plus a caching mechanism (and we could use a global map plus a A late final instance variable would presumably not support initialization before the body of the constructor runs (so the primary constructor syntax would not allow us to initialize this kind of variable, it must be initialized "late"). Again, we could implement the checks and the dynamic error to get this behavior anyway, verbosely, so there's not much gained by outlawing it. |
We can definitely allow Struct instances cannot and must not have late fields.
That's allowed today. |
Which is the reason why I suggested that they would be
and not in the argument list which turns into the primary constructor. So we agree on that.
Ah, that's interesting! I agree, after a bit of thinking: The basic semantics of final instance variables (late or not) ensures that they do not mutate (read such a variable twice, and you will get the same result). However, if a struct instance is boxed, and it contains a As seen from the history of each of these copies of the struct instance you could claim that there is nothing wrong with this behavior ("you asked for it"), but it is surely going to be impossible to reason about in practice. So I agree: We definitely cannot let late initialization occur for a struct instance after an unboxing or boxing step, and there is no reasonable way to enforce that the initialization occurs before the first such event. Hence, no late instance variables are allowed in a struct. |
In the struct and extension struct proposal (#2360), the proposal adds primary constructors to structs. The generated primary constructor uses positional parameters, but there is discussion of the alternative approach of using named parameters. That is, the proposal is that the following:
is treated as roughly equivalent to:
An alternative is to have the generated constructor use named parameters:
When @munificent has scraped corpuses of code before, I believe his conclusion is that code is split fairly evenly as to which form to use.
We could also choose to allow the user to specify: that is, we could allow the primary constructor to list zero or more parameters inside of braces, which would then become named parameters.
There are some obvious restrictions around the combinations of optional and named parameters, but otherwise I think this works out fine.
The text was updated successfully, but these errors were encountered: