Extensible destructuring proposal

Isiah Meadows isiahmeadows at gmail.com
Thu Aug 6 18:21:41 UTC 2015


I meant "statically compiled" in the sense of AOT compiled, in the veins of
C++, Java, TypeScript, etc.

On Wed, Aug 5, 2015, 14:04 Brendan Eich <brendan at mozilla.org> wrote:

> Missing reply text? Your message which you cited in full made it to the
> list.
>
> BTW "statically compiled" doesn't make sense -- did you mean "statically
> typed", or "with fully static name binding"? JS does lack those,
> although strict mode gets close to fully static name binding (the global
> object can still sprout new properties that may be referenced via free
> variables).
>
> /be
>
> Isiah Meadows wrote:
> >
> >
> >
> > On Wed, Aug 5, 2015, 04:29 Isiah Meadows <impinball at gmail.com
> > <mailto:impinball at gmail.com>> wrote:
> >
> >     Good point. I did make most of the natives identity functions
> >     returning the object itself for most cases with the prolyfill,
> >     which engines should easily detect at run time and inline into
> >     nothingness. But I do see your point. As proposed, I know it's
> >     still incomplete in its core functionality (pattern matching on
> >     array literals would be a bit more interesting), but the other
> >     core problem is this: JavaScript isn't statically compiled. Nearly
> >     every language with patten matching is. It's much easier to
> >     optimize this into something decently performant in a static
> >     context (TypeScript as an example).
> >
> >
> >     On Wed, Aug 5, 2015, 04:19 Andreas Rossberg <rossberg at google.com
> >     <mailto:rossberg at google.com>> wrote:
> >
> >         On 5 August 2015 at 09:27, Isiah Meadows <impinball at gmail.com
> >         <mailto:impinball at gmail.com>> wrote:
> >
> >             Damnit...forgot to fix the subject.
> >
> >             On Wed, Aug 5, 2015 at 3:20 AM, Isiah Meadows
> >             <impinball at gmail.com <mailto:impinball at gmail.com>> wrote:
> >
> >                 Wait...this got me thinking... The proposal itself
> >                 doesn't bring along a lot of merits, but it seems like
> >                 it could be a great stepping stone to a limited
> >                 pattern matching syntax. This would probably be a
> >                 little more justifiable IMHO than merely a custom
> >                 destructuring syntax. Maybe something like this:
> >
> >
> >         I intentionally did not bring up pattern matching. That indeed
> >         is what views are usually wanted for. But then you need to be
> >         much more careful in designing a mechanism that avoids
> >         re-transforming the scrutinee for every tested case! Because
> >         that would be very costly. For that reason, I fear that the
> >         feature as proposed would interact badly with any future
> >         pattern matching mechanism, in the sense that it would
> >         encourage very costly usage that cannot be optimised.
> >
> >         /Andreas
> >
> >
> >
> >                 ```js
> >                 Type[Symbol.pattern] = (obj) => {
> >                   return [obj.a, obj.b];
> >                 }
> >
> >                 const Other = {
> >                   [Symbol.pattern]: obj => obj,
> >                 }
> >
> >                 class None {
> >                   static [Symbol.pattern](obj) {
> >                     return obj
> >                   }
> >                 }
> >
> >                 // Pattern matching, signaled by `in` here
> >                 switch (object) in {
> >                   case Type([a, b]): return a + b
> >                   case Other({a, b}): return a * b
> >                   case None: return undefined // Special case, no
> >                 identifier initialized
> >                 }
> >
> >                 // Extensible destructuring, easy to implement with
> >                 the pattern
> >                 // matching
> >                 let Type([a, b]) = object
> >                 let Other({a, b}) = object
> >                 ```
> >
> >                 In the destructuring phase for both, I was thinking
> >                 about the following semantics to assert the type,
> >                 based on `typeof` and the prototype. This will help
> >                 engines in optimizing this as well as some type safety
> >                 for all of us.
> >
> >                 ```js
> >                 function _checkProto(object, Type) {
> >                   // Note: Type[Symbol.pattern] must be callable
> >                   if (typeof Type[Symbol.pattern] !== 'function')
> >                 throw new TypeError()
> >                   if (typeof Type === 'function') {
> >                     if (type === Array) {
> >                       return Array.isArray(object)
> >                     } else {
> >                       return object instanceof Type
> >                     }
> >                   } else {
> >                     return Object.prototype.isPrototypeOf.call(Type,
> >                 object)
> >                   }
> >                 }
> >
> >                 function isInstance(object, Type) {
> >                   switch (typeof object) {
> >                     case 'object': return obj != null &&
> >                 _checkProto(object, Type)
> >                     case 'function': return Type === Function
> >                     case 'boolean': return Type === Boolean
> >                     case 'number': return Type === Number
> >                     case 'string': return Type === String
> >                     case 'symbol': return Type === Symbol
> >                     case 'undefined': return false
> >                   }
> >                 }
> >                 ```
> >
> >                 Finally, get the result and do a basic variable
> >                 pattern assignment, LHS being the operand, and RHS
> >                 calling `Type[Symbol.pattern]`.
> >
> >                 The `switch` statement example would (roughly) desugar
> >                 to the following:
> >
> >                 ```js
> >                 switch (true) {
> >                   case isInstance(object, Type):
> >                     let [a, b] = Type[Symbol.pattern](object)
> >                     return a + b
> >
> >                   case isInstance(object, Other):
> >                     let {a, b} = Other[Symbol.pattern](object)
> >                     return a * b
> >
> >                   case isInstance(object, None):
> >                     return undefined
> >                 }
> >                 ```
> >
> >                 The destructuring examples would (roughly) desugar to
> >                 this:
> >
> >                 ```js
> >                 if (!isInstance(object, Type)) throw new TypeError()
> >                 let [a, b] = Type[Symbol.pattern](object)
> >                 if (!isInstance(object, Other)) throw new TypeError()
> >                 let {a, b} = Other[Symbol.pattern](object)
> >                 ```
> >
> >                 The type assertions will help engines in optimizing
> >                 this, and it'll also make this safer. It also just
> >                 makes sense for pattern matching.
> >
> >                 As a side effect, you can get the value without
> >                 destructuring (i.e. the literal result of
> >                 `Symbol.pattern`) via this:
> >
> >                 ```js
> >                 let Map(m) = someMap
> >                 let m = Map[Symbol.pattern](someMap)
> >                 ```
> >
> >                 I, myself, came up with a Scala-inspired case class
> >                 concept
> >                 <https://gist.github.com/impinball/add0b0645ce74214f5aa>
> >                 based on this, and used it to make try-catch handling
> >                 a little more Promise-like, which I know quite a few
> >                 TypeScript users would eat up in a hurry
> >                 <https://github.com/Microsoft/TypeScript/issues/186>
> >                 (particularly the sum type implementation). I also
> >                 created a little toy Option/Maybe implementation
> >                 <https://gist.github.com/impinball/4833dc420b60ad0aca73>
> >                 using pattern matching to ease `null`/`undefined`
> >                 handling.
> >
> >                 And also, check out my gist
> >                 <https://gist.github.com/impinball/62ac17d8fa9a20b4d73d>
> >                 for a proposed `Symbol.pattern` prolyfill for the
> >                 primitive types. That would allow for things like this:
> >
> >                 ```js
> >                 switch (list) in {
> >                   case Array([a, b, c]): return doSomething(a, b, c)
> >                   case Map({a, b, c}): return doSomethingElse(a, b, c)
> >                   default: return addressBadType(list)
> >                 }
> >                 ```
> >
> >                 > ---------- Forwarded message ----------
> >                 > From: Andreas Rossberg <rossberg at google.com
> >                 <mailto:rossberg at google.com>>
> >                 > To: "Samuel Hapák" <samuel.hapak at vacuumapps.com
> >                 <mailto:samuel.hapak at vacuumapps.com>>
> >                 > Cc: es-discuss <es-discuss at mozilla.org
> >                 <mailto:es-discuss at mozilla.org>>
> >                 > Date: Tue, 4 Aug 2015 14:26:45 +0200
> >                 > Subject: Re: Extensible destructuring proposal
> >                 > On 31 July 2015 at 20:09, Samuel Hapák
> >                 <samuel.hapak at vacuumapps.com
> >                 <mailto:samuel.hapak at vacuumapps.com>> wrote:
> >                 >>
> >                 >> So, do you still have objections against this
> >                 proposal? Could we summarize them?
> >                 >>
> >                 >> @Andreas, do you still think that there is category
> >                 error involved?
> >                 >
> >                 >
> >                 > If you want to overload existing object pattern
> >                 syntax, then yes, definitely. I strongly disagree with
> >                 that. It breaks regularity and substitutability (you
> >                 cannot pass a map to where a generic object is expected).
> >                 >
> >                 > As for a more Scala-like variant with distinguished
> >                 syntax, I'm fine with that semantically. But I still
> >                 don't buy the specific motivation with maps. Can you
> >                 give a practical example where you'd want to create a
> >                 map (immutable or not) for something that is just a
> >                 record of statically known shape? And explain _why_
> >                 you need to do that? Surely it can't be immutability,
> >                 since objects can be frozen, too.
> >                 >
> >                 > To be clear, I wouldn't reject such a feature
> >                 outright. In fact, in a language with abstract data
> >                 types, "views", as they are sometimes called in
> >                 literature, can be valuable. But they are also
> >                 notorious for a high complexity cost vs minor
> >                 convenience they typically provide. In particular, it
> >                 is no longer to write
> >                 >
> >                 >   let {a: x, b: y} = unMap(map)
> >                 >
> >                 > as you can today, then it would be to move the
> >                 transformation to the pattern:
> >                 >
> >                 >   let Map({a: x, b: y}) = map
> >                 >
> >                 > So I encourage you to come up with more convincing
> >                 examples in the JavaScript context. Short of that, I'd
> >                 argue that the complexity is not justified, at least
> >                 for the time being.
> >                 >
> >                 > /Andreas
> >
> >
> >                 --
> >                 Isiah Meadows
> >
> >
> >
> >
> >             --
> >             Isiah Meadows
> >
> > _______________________________________________
> > es-discuss mailing list
> > es-discuss at mozilla.org
> > https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150806/e7c7c118/attachment-0001.html>


More information about the es-discuss mailing list