-
Notifications
You must be signed in to change notification settings - Fork 302
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
semantics of closing "top" #3727
Comments
Copying your example for reference:
FWIW, it's not surprising to me! I say that only as a sample in the discussion, certainly not as a point of reference. For me, the notion of something being closed only applies to structure, i.e. lists and structs. But with
Noting that
As you say, , Contrast (play):
which gives:
In this example, beyond the field The only reason I say this out loud is to point out that
Per my comments above, there is nothing to close here.
I'd tend to agree that this looks a bit odd. My understanding is that it's a consequence of embedding. On this point I reference our offline discussion regarding more explicit syntax for embedding that would cause this to disappear.
I'm not sure I follow this argument so an example/question by way of reply:
Has this not violated the property you outlined? In any case, I'm not clear that property has to hold in general, in CUE at least. It's a breaking change, to my mind, to make such a definition more specific. The only safe change, in general, would be to make is less specific. |
As a general rule, I would expect subsumption to obey transitivity. That is, if k is more specific than j, and j is more specific than i, then k should be more specific than i. This seems quite fundamental. But the fact that closing top does not do anything, breaks this.
all fine. But:
We know that j is more specific that i. We also know that k is more specific than j. This is because really, we should spell them as:
so both have all the fields defined, but for the field
What is seemingly wrong is that replacing the most general value, i with the value j (that we know is between i and k) produces an error. I think it makes sense for ik to error in addition to jk. |
It is also not surprising to me: Note that There is an orthogonal concern of As a general principle, |
with the mentioned syntax this would still be A big reason for this syntax (though not the only one) is the interaction with comprehensions, which always emit a value enclosed in braces |
With |
Actually they are not: |
For completeness of the argument, a regular field is more specific than a required field which is more specific than an optional field. |
Apparently closing top doesn't do anything. I find this is illogical, and think should be changed.
This does not cause an error.
I think this is surprising, and a foot-gun.
It now means we have 3 ways to spell forced-open:
#s: f: {...}
This is (imo) by far the easiest to understand. It looks like a struct....
only has one role in the language. This can't really be misinterpreted.#s: f: _
This doesn't look like a struct, and it looks like it should be closed. Yet we allow it to unify with structs that add fields.#s: f: {_}
This is surprising syntax. It looks like a struct, yet we allow it to unify with things that are not structs. E.g.o: #s & {f: 1}
It is illogical. Consider this:
#x: number
Every int will satisfy this (as does
int
). E.g. addingo: #x & 5
won't cause an error. If I make the original a bit more specific:#x: int
then still every int will satisfy this. So this is a basic transitive property: if we have "i is more specific than j is more specific than k" and we replace a "k" with a "j" then we still require "i" to unify without error with "j".
But consider this:
#y: _
Currently, every struct will satisfy this (as does
{}
). E.g. addingo: #y & {f: 1}
won't cause an error. Yet, if I make the original a bit more specific:#y: {}
now the behaviour has inverted and values that unified before no longer unify. We have broken transitivity. This causes surprise for users, and makes the mental model harder for everyone to hold -- as every caveat and corner case does.
Therefore, I think it is preferable for
to cause an error -- field not allowed.
There is nothing problematic or undesirable about a closed top precluding any non-empty struct. If the user really wants to allow any struct, then
{...}
is available, and if they want to allow any value at all, then{_}
is available (or{...} | _
which I prefer). I think because{_}
is such strange syntax it avoids the point-of-surprise -- you would see it and think "well that's odd, it must be there for a good reason".The text was updated successfully, but these errors were encountered: