Comments (22)
A "spread" on the
lhs
will create an object or array, not a record or tuple.
I guess in most cases programmers want record/tuple when destructuring record/tuple. So:
const [a, ...rest] = #[1, 2, 3]
rest === #[2, 3] // expect true, actual false
// Programmers need to convert it to record/tuple manually
const restTuple = #[...rest]
There are several options we could consider:
- Let spread create record/tuple when destructuring record/tuple.
const [a, ...rest] = #[1, 2, 3]
rest === #[2, 3] // true
Pros: Match programmer's expectation in most cases (I suppose)
Cons: May break old code which assume the result of destructuring are always object/array.
- Introduce a special syntax, for example:
const [a, #...rest] = #[1, 2, 3]
Pros: new syntax never affect old code
Cons: another new syntax
from proposal-record-tuple.
@dcporter I agree that we should permit the first part of your sample, but I don't see why we should prohibit the second part. Can't we just say that that's an Object? It's always possible to spread it out into a Record later if that's desired (even as this construct is a bit awkward).
from proposal-record-tuple.
Note that you can do this all with strings as well:
> const { length, ...props } = "hello"
> length
5
> props
Object(5) [ "h", "e", "l", "l", "o" ] // How Firefox console displays it
I think the semantics of destructuring point to a clear answer by analogy here, that we just blindly create an Object rather than a Record in this kind of case.
from proposal-record-tuple.
Destructuring is really nice though — instead of deferring the whole thing to a future proposal, could we just disallow the rest operator?
const rec = #{ a: "a", nestedRec: #{ deepA: "deepA" } };
const { a, nestedRec } = rec;
assert(a === "a"); // all good
assert(nestedRec === #{ deepA: "deepA" }); // all good
const { a, ...rest } = rec; // runtime error
When destructuring an object, you just get back whatever's inside. In this case, what's inside is (and can only be) a primitive or another record/tuple, so you'd get back those. So there's no controversy here, right? Just with the ...rest
example above, so I would like to know if we can specifically disallow that.
from proposal-record-tuple.
@ljharb right: I’m now saying that destructuring with {} on the right left should result in an Object, and it would be very surprising if it didn’t. And this makes me think that having #{}
syntax on the right left hand to result in a Record does make sense (though it may be complex / cuddly fiddly enough to punt to a future proposal).
from proposal-record-tuple.
@caiolima if I remember correctly, destructuring is specified as a series of steps being done to set variable values (which is why a value can dynamically use the value of a previous variable in the destructuring). In this case, I see no reason why the right side cannot be an object and the left a record, and vice versa.
from proposal-record-tuple.
The right hand side of destructuring is an expression that’s allowed to be any non-nullish object; it seems exceedingly strange to allow disallow record/tuple primitives. Do you mean the left hand side?
It makes no sense to me to use record/tuple syntax on the left hand side, since that’s object-like syntax for creating variables, not for creating an object (and thus, not for creating records/tuples).
from proposal-record-tuple.
Yes, it is - i don’t even see how it could possibly make any sense to allow it.
from proposal-record-tuple.
Sounds good, we should write down it's not possible to destructure them
from proposal-record-tuple.
(gyaaaargh left not right!)
from proposal-record-tuple.
@dcporter precisely :-D
from proposal-record-tuple.
you could still do export const #{x, y, ...z} = record
, no? it'd just make the values be Records.
from proposal-record-tuple.
@ljharb: Well, yes, I believe they should be. It's just not in the current proposal, and should be either added, or explicitly specified that it is not supported.
(not sure about that export
in your example. typo, or did I miss something important?)
from proposal-record-tuple.
it should be the same with or without the export.
from proposal-record-tuple.
In the case of using let #{...rest} = exp
, what would be the behavior when exp
evaluates to an Object? Also, What happens if we then have an record into Object destructuring?
I can think in 2 options here that is throwing TypeError or coercing types. However, I don’t like the idea of throwing a TypeError, because it means that we would have some inflexibility when using destructuring into formal parameters. I also don’t like the idea of having type coercion here, because they may lead to a lot of confusion.
from proposal-record-tuple.
I want to propose that destructuring with record and tuple syntax be a syntax error (at least in this initial proposal). We don't allow most kinds of literals on the right left hand side, and destructuring objects and arrays is generally liberal and not throw-y. I could imagine pattern matching records and tuples, but that's different.
from proposal-record-tuple.
@ljharb Heh, yes, edited my comment to refer to the left, not right, side. Is it accurate to say that our proposals (of banning this construct) match?
from proposal-record-tuple.
Hmm — splitting up a record and getting an object felt wrong. But now I'm poking around in the console and I see that I can use const {}
destructuring on arrays to get an object back, so of course the left-hand syntax is what controls what sort of object you get back (see below*), so { ...rest }
in this case would be an Object, you're right.
Given that, I think it does make sense to allow the #
on the left-hand side, with the right-hand side being anything that has keys. I would be fine with punting this to a future proposal, but now I disagree with @ljharb that "It makes no sense to me to use record/tuple syntax on the left hand side, since that’s object-like syntax for creating variables, not for creating an object (and thus, not for creating records/tuples)" — the left-hand notation can already be used to specify what you want back from ...rest
.
* Object-destructuring an array:
const arr = [0, 1, 2];
const { 1: one, ...rest } = arr;
console.log(one); // 1
console.log(rest); // { 0: 0, 2: 2 }
from proposal-record-tuple.
You’re right that a rest arg produces a container value; it does seem reasonable to me not necessarily that you can determine what you get on the LHS with syntax, but that perhaps a rest arg from a Record/Tuple is a Record/Tuple automatically?
from proposal-record-tuple.
In your example however, to contradict my last comment; note that rest
isn’t any array, it’s a plain object, so having it be a plain object when the RHS is a Record also shouldn’t be surprising.
from proposal-record-tuple.
I agree.
(PS I also meant "fiddly" not "cuddly" in my previous; there's probably no less cuddly character than #
)
@ljharb you gave my last both a const #{…}
? If so then cheers (and we can revisit in a future proposal
from proposal-record-tuple.
The spread operator on LHS has a lot of real-world good use cases like below.
const myFunc = ({ foo, ...rest}) => {
console.log(rest == #{bar: "Bar", count: 2})
}
myFunc(#{foo: "Foo", bar: "Bar", count: 2})
If you guys think it can break old code where destructuring is always an object then adding a new syntax like below will still be very useful for developers.
const myFunc = ({ foo, #...rest}) => { }
from proposal-record-tuple.
Related Issues (20)
- Review feedback HOT 6
- Stage 3 Review HOT 5
- Dynamic ToPrimitive handling of Tuple exotic objects differs from Records HOT 12
- `DefineOwnProperty` for tuples is inconsistent
- IsValidTupleIndex needs to check for non-integral numbers HOT 1
- How about classes? HOT 6
- Record keys are deduplicated, but should duplicates generate a thrown error? HOT 5
- brad4d Stage 3 Review feedback HOT 9
- Forbid hosts creating an impossible records/tuples
- Can we agree on a list of design goals for the README? HOT 2
- Upgradeable ArrayBuffers HOT 5
- add support for tuples to {Async,}Iterator.prototype.flatMap and {Async,}Iterator.from
- `Record` name conflict with Typescript HOT 1
- Why mixing immutability and tuples ? HOT 5
- `let` binding record and tuple should be writable HOT 6
- Some syntactic sugar: no need to insert # before every nested structure HOT 4
- Is this planned for ES14? HOT 6
- What about sets? HOT 14
- Record and Tuple creation should be recursive. HOT 5
- Can I use? HOT 9
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from proposal-record-tuple.