-
Notifications
You must be signed in to change notification settings - Fork 45
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
Structure matching syntax #95
base: master
Are you sure you want to change the base?
Conversation
I think that we should leave the proposed |
From my POV, the thing that sunk the previous RFCs were exactly the questions that the That's the reason this is not an implementation RFC, by the way. The intention is that we align on overall direction first, and then implement in parts, as needed. To quote Andy from the previous thread:
It's worth noting that this RFC already punts on many of the integration problems we found, such as how destructuring assignments should work (or if they should work, given myself and Hunter don't know of any languages that support this). If we punt on substantially more than we do already, we'll just be back to the old RFC, at which point I don't know what different result we expect to find. So we need to decide on what our approaches will be for those facets of the feature, hence all of the extra syntax above what we already agreed upon. Whether we decide to support each feature or drop them from the spec, the decision must be documented, not deferred. |
Dropping the |
Coming into this a bit late I guess, but wanted to just ask some questions. Is there some issue with copying the JavaScript syntax wholesale? It's quite well thought out and tried and tested. For example one question I have is, why is it necessary to have a dot prefix for the destructured keys instead of:
|
I don't entirely disagree with that idea personally, but IIRC others shot this down already. The main trouble comes from the fact that array literals would look the same as keyed table destructuring: -- this would not work as expected, despite looking visually similar
local { foo, bar } = { "foo", "bar" } This was considered a showstopper for that syntax in particular. Beyond that, the square brackets idea has been floated a few times, but each time there's generally some disapproval since the only other time Luau uses square brackets is for indexing; we dont use I think JS has a well designed syntax for JS, but in the context of Luau there's multiple arguments against some of its choices. As for: local foo, bar, ...rest = t This would be backwards incompatible, as Luau supports multiple returns. Today, this runs: local foo, bar, baz = { "hello" }
print(foo, bar, baz) --> { [1] = "hello" } nil nil |
I very much prefer something along the lines of what @rihok suggested at the very bottom of the code sample, possibly something that outlines similarly to: local KeyedTable = {
Hello = true;
[5] = false;
[Instance] = 5;
}
local PackedTable = table.pack(1, 2)
local NestedTable = {
Nested = {
World = true;
};
}
local [ ["Hello"] = A, [5] = B, [Instance] = C ] = KeyedTable
local [ [1] = D, [2] = E, ["n"] = F ] = PackedTable
local [ ["Nested"] = [ ["World"] = G ] ] = NestedTable I assume square brackets here would be an understandable extension of the Luau language given that square brackets are only used for indexing (a point illustrated by @dphblox) and table destructuring is simply an abstraction of that. A few things to touch on surrounding this:
local [ Hello = A, [5] = B, [Instance] = C ] = KeyedTable
local [ Nested: [ World: G ] ] = NestedTable
local something = someTable
[ SomeIndex: GlobalVariable ] = someTable This has the same behavior as parentheses do in the language and results in roughly the same error contextually. This shouldn't be seen as a drawback and instead a reinforcement of the languages already well established behavior. I don't know what the implications are on parser complexity in regards to this or whether or not this fits within the purview/scope of this RFC. But I believe it's a fun and reasonable suggestion purely in terms of syntax. |
I would be somewhat OK with this, but it's a little weird that we would use square brackets both to surround the keys and to surround the whole matcher. Perhaps it would help with the "array problem": local [ these, are, keys ] = data
local { these, are, consecutive, values } = data But this would still be inverse of JS, which could be a stumbling block. IIRC, this is part of what caused the original RFC to fail, hence the dot prefixes. The older RFC has more details on that whole thing.
Colons are used for type annotations, so it would be almost certainly inappropriate to use them here. |
Here, let me throw out a few crazy syntax ideas, specifically trying to figure out how best to make array/dict difference obvious: local {in these, are, keys} = data
local {...these, are, consecutive, values} = data local in {these, are, keys} = data
local ...{these, are, consecutive, values} = data |
I think I'll try and write down my full chain of thoughts at the moment around the array and reassignment comments from the old RFC, as well as some syntax comments more generally. Take all this syntax with a pinch of salt - it's just to illustrate. Unlike JS, Luau allows you to shuttle around multiple values at once, making unpacking the natural paradigm for array destructuring: local these, are, consecutive, values = table.unpack(data, 1, data.n) So if we were to suggest any syntax there, it really feels like it ought to be expression-side, not assignment-side: local these, are, consecutive, values = ...data Naturally I would be inclined to extend that to keys (thus making this RFC redundant), but that introduces the problem of having to specify the keys twice in almost all situations: local these, are, keys = ...data["these", "are", "keys"] That's the grounds upon which I think the original destructuring RFC was made, and probably what we should focus on solving. That also aligns with the discussions we've had above. Trying to make this work for arrays seems misguided and I don't reckon it's even relevant. Now onto syntax. One of my earlier explorations was having a "destructuring assignment", though I was concerned about it looking too much like a compound assignment, or like it's unpacking values positionally: local these, are, keys ...= data In my eyes, the problem there is that throughout the rest of Luau, the names of those identifiers are not significant - only their positions are. Therefore, if the names are going to be significant, it's worthwhile to alter how those names are presented to make that clear. That's what the original RFC did. I'd say dot prefixes seem like a sensible and low-syntax way to indicate those names are keys. local .foo, .bar, .baz = data Of course, without the local thing
local function usesThing()
task.delay(1, function()
print(thing)
end)
end
local otherThings, foo, bar
.thing, .otherThings, .foo, .bar = getThings() Forward declaration is a little bit of a code smell IMO (though not always!), it feels unintuitive for people to destructure in this position, and JS doesn't support destructuring when assigning - only when declaring - so I would be personally OK dropping this requirement, though I'm not the person who brought it up in the first place. So all of that is my bias coming into this. I'm not saying we should do any of the above, but that's the general direction I lean in philosophically. My aim is to try and enmesh that with the previous RFC and the syntax everyone seemed to be OK with at the time. |
Gathering consensus on the destructuring syntax inside of the braces (i.e. punting on other issues explicitly), so we can align on this with the community.
Rendered.