-
Notifications
You must be signed in to change notification settings - Fork 3
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
Problem statement #18
Comments
You are correct. It's the ability to evaluate code that affects destructuring of an input. Getters only affect how an object produces an output for a given property.
This proposal is closely aligned with Pattern Matching, as extractors will follow the same semantics in both cases.
Extractors are synonymous with custom matchers in the pattern matching proposal. The majority use case for extractors will be to define a mechanism to validate the subject (i.e., the RHS of the assignment, or the match subject) and invert construction to acquire the inputs, i.e.: const p = new Point(1, 2);
const Point(x, y) = p;
x; // 1
y; // 2 Extractors fill a capability gap in both destructuring and the pattern matching proposal, but can't serve as a pattern matching mechanism solely on their own. |
Great, I think if we can tighten the language around the motivation, it might be clearer to people who see it for the first time. |
How does this sound:
We're not exactly customizing destructuring, as |
Maybe I'm missing something, but starting from the example in #15 (comment), wouldn't something like this be much simpler and already possible? let x1 = line.p1.x;
let y1 = line.p1.y;
let x2 = line.p2.x;
let y2 = line.p2.y; and if it's a concern that we're accessing the same property of let { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } } = line; presuming, of course, that the So why are we introducing a more complicated way of doing a thing that's already possible? Is there something that extractors make possible that isn't currently possible? |
Extractors extend the destructuring paradigm to add support for user-defined input validation and transformation. The comment you referenced only intended to describe a semantic equivalent in current JS for a very narrow case. What is missing from that example is the implementation of class Point {
#x;
#y;
constructor(x, y) {
this.#x = x;
this.#y = y;
}
// NOTE: commented out to illustrate extractor flexibility in extracting
// private fields, while keeping the author of `Point` in control
// how private state can be accessed.
//get x() { return this.#x; }
//get y() { return this.#y; }
static [Symbol.customMatcher](subject) {
return #x in subject ? [subject.#x, subject.#y] : false;
}
}
// destructuring
const Point(x, y) = new Point(1, 2);
x; // 1
y; // 2
// pattern matching
match (p) {
when Point(let x, let y): …;
} The While the same operations can be performed across multiple statements with something like a static Extractors encourage a leaner coding style that is often preferred by JS developers and is regularly seen in other languages with language features like Pattern Matching: // (assumes Point.{ x, y } are public for the purpose of this example)
const { p1, p2 } = line; // top-level destructuring
if (!(p1 instanceof Point) || !(p2 instanceof Point)) throw new Error(); // data validation
const { x: x1, y: y1 } = p1; // nested destructuring
const { x: x2, y: y2 } = p2; // nested destructuring
// vs
const { p1: Point(x1, y1), p2: Point(x2, y2) } = line; In addition to the conciseness of Extractors in destructuring, they also allow for optimal short-circuiting in Pattern Matching: match (shape) {
when { p1: Point(let p1), p2: Point(let p2) }: drawLine(p1, p2);
...
} Here, the brand check in Another place they shine is within parameter lists where there is no Statement context within which to split out code without shifting work to the body: function encloseLineInRect(
{p1: Point(x1, y1), p2: Point(x2, y2)},
padding = defaultPadding(x1 - x2, y1 - y2)
) {
const xMin = Math.min(x1, x2) - padding;
const xMax = Math.max(x1, x2) + padding;
const yMin = Math.min(y1, y2) - padding;
const yMax = Math.max(y1, y2) + padding;
return new Rect(xMin, yMin, xMax, yMax);
}
function defaultPadding(dx, dy) {
// use larger padding if x or y coordinates are close
if (Math.abs(dx) < 0.5 || Math.abs(dy) < 0.5) {
return 2;
}
return 1;
}
const rect = encloseLineInRect(line); Here, extractors let you validate the input arguments and extract coordinates without needing to shift default argument handling for Many of the above examples are more complex cases than what is generally the norm with similar syntax in Scala, Rust, C#, F#, etc., which often looks more like this: // destructuring
const Message.Move(x, y) = msg;
// pattern matching
match (opt) {
when Option.Some(let value): ...;
when Option.None: ...;
}
// more pattern matching
if (opt is Option.Some(let value)) {
console.log(value);
} However, the extractor syntax is designed to be consistent with existing JS destructuring mechanisms as well as with the pattern matching proposal, which allows for a wide range of use cases. |
This sounds great and resolves my concern! |
Some questions came up around the motivation, in particular the current wording:
"ECMAScript currently has no mechanism for executing user-defined logic during destructuring"
From reading the proposal, it doesn't seem that arbitrary user logic during destructuring is the goal. In a sense, getters do this as well. The proposal rather seems to enable user customized destructuring? or something to this effect? Maybe I am wrong here?
I see some overlap with the motivation of pattern matching:
"There are many ways to match values in the language, but there are no ways to match patterns beyond regular expressions for strings. However, wanting to take different actions based on patterns in a given value is a very common desire: do X if the value has a foo property, do Y if it contains three or more items, etc."
This proposal seems to allow users to customize the destructuring of an object according to a pattern that the user defines?
The text was updated successfully, but these errors were encountered: