-
Notifications
You must be signed in to change notification settings - Fork 213
How should name collision in tuples be handled. #1291
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
Comments
My proposal: (int, int, {int x, int hashCode}) p = (0, 1, x: 2, hashCode: 3);
print(p[0]); // 0
print(p[1]); // 1
print(p.x); // 2
print(p[#x]); // 2
print(p[#hashCode]); // 3 Again, there is no You can use (This means that tuple types do occupy the This gives a readable projection syntax. It requires named members to be added for positional entries, which avoids one source of name conflict, and it provides a canonical way to access any entry, as well as a convenient way for unconflicted named entries. The |
Looks good! However, it won't take long before we get this request: (int, int, {int x, int hashCode}) p = (0, 1, x: 2, hashCode: 3);
for (var index in [0, 1, #x, #hashCode]) print(p[index]); We could handle this by a compile-time loop unrolling, but I guess the answer will be "Just say no!". ;-) |
Yeah, I think I made that an explicit error in some draft of the proposal but accidentally forgot it. I think this should be an error.
This is a fair point, but I wonder if the complexity needed to support fully generalizing over all possible parameter lists carries its weight.
I think using the I get the principle of not wanting to have certain member names treated as specially by the language, but I think adding a whole separate kind of "record field access" syntax and semantics to the language feels like a lot of mechanism for not a lot of value in return. We don't give you any way to define a method named |
(For the record, I have always wanted you to use |
Traditional according to what tradition? Using Kotlin uses I would have considered
Me too. But not doing that hasn't seemed to have caused us much pain. |
In my book, that's a signal to not do something. :)
I kind of like that and have idly considered it. It has at least one edge case ambiguity: extension on (String, String) {
method() {
print(.0); // Oops! double literal not a field access on implicit this.
}
} But, overall, I think it's kind of strange looking and probably not worth adding new syntax for.
That's OK too. Another option is
var record = ("str", 3);
var i = isTuesday ? 0 : 1;
var field = record[i]; What is the static type of |
I'm actually somewhat interested in this syntax, and I would say that |
The question about the least upper bound of two tuple/record types is basically determined by the subtype structure (cf. #1278): If we have For the treatment of Hence, it seems consistent to require for |
For LUB, I'd go with
I don't want the var p1 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, foo: 42);
var p2 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, bar: 42);
var p = test ? p1 : p2; // infer Destructure10<int, int, ..., int>.
print (p.field0); // prints "1"; then it works, but if you then add an element to p1: var p1 = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, foo: 42); then there is no |
@tatumizer It's one way of thinking, but it requires Because of assignability, we should be able to do the un-conditional assignment void foo(int x, {int y = 0}) => ...;
foo(1, 1, foo: 0, bar: 0); That looks like, and probably is, an error. We do not allow it. Tuple assignment is very closely related to parameter passing, so having significantly different behavior is a design smell. For that reason, the current specification does not have any subtype relations between tuple types based on common sub-structure. |
My earlier comment on this was: I think using the
That's what the proposal states too.
You're correct. It's logically consistent and sound. In other languages, this is called "width subtyping" or "row polymorphism". However, I think it's looser than we want and is more likely to mask bugs than do anything useful. The goal of a type system isn't necessarily to statically allow all operations that would not fail at runtime. It's to help users write the code they intend to write and help them not write the code they don't intend to write. |
I went ahead and removed the synthesized getter names for positional fields from the proposal. This means that currently the only way to access positional fields is using pattern matching and destructuring. I'll re-open this issue to talk about potentially adding a new syntax for accessing those fields. |
...and there is a newer issue to discuss this that I think has more up-to-date conversation, so I'll close this one in favor of that: #2388. |
The current proposal for tuples introduces a
field1
getter for a positional entry and aname
getter for a named entry namedname
.It's made a compile-time error to have a named entry with the same name as a member of
Object
(toString
,runtimeType
,noSuchMethod
,hashCode
).It's not defined what happens if a named entry has the name
field1
and there is also a positional entry which would get that name, It should probably also be an error.However, all these restrictions may interfere with uses of tuples. A function can have a named parameter named
toString
, and if you can't create a tuple with a named entry with that name, then you can't spread a tuple as all the arguments of a function call of that function. You can't properly abstract over function arguments if the tuples are restricted in names in ways that function parameters are not.The
fieldX
names themselves may be open to discussion. The language specification doesn't use the name "field" (it's "instance varibles"), so hard-coding the term into the language seems a little odd. Any name can cause a problemShould we do something else than naming the positional entries? Should we allow named entries with any name, and provide access to them?
The text was updated successfully, but these errors were encountered: