operator overloading proposal

Kevin Barabash kevinb at khanacademy.org
Fri May 20 23:34:15 UTC 2016


Good point.  In my original post I mentioned introducing a `"use
overloading"` directive.  We could throw when trying to use this directive
with the `"use asm"` directive.

We can definitely wait on this.

Definitely looking forward to static typing.  Is
https://github.com/sirisian/ecmascript-types the proposal to be following?

On Thu, May 19, 2016 at 12:35 PM, Isiah Meadows <isiahmeadows at gmail.com>
wrote:

> That is a valid concern. As good as having this feature might sound, could
> this discussion be revisited after static types are addressed and we see
> how WebAssembly pans out? The reason I ask the latter is because of the
> above concern about asm.js, which WebAssembly aims to replace in an IMHO
> far superior way. Depending on the uptake of WebAssembly a few years down
> the road, it may later become practical to break forward compatibility in
> that way due to lack of usage. It's not a common use case, though, to send
> an object of unknown type to an asm.js function, and replacing native
> methods fails validation, so the risk isn't as high as it might seem.
>
> On Thu, May 19, 2016, 12:36 John Lenz <concavelenz at gmail.com> wrote:
>
>> I have some concerns. With the short circuiting operators:
>>
>>       Commutative operators, +, *, &&, ||, &, |, ^, automatically flip
>> the order of operands when their types are different.
>>
>> && and || can not "flip" and routing them through a method is not
>> compatible with short-circuiting.
>>
>> Generally, there are a lot of things that can go wrong in interop with
>> existing code: unlike some other languages in JavaScript operators are
>> often used to coerse to a know type:   "+value" to a number, "x|0" to  an
>> 32-bit integer, etc.  These kinds of guarantees are what "asm.js" is based
>> on, for example, and having to wait until type feedback is available to
>> perform its optimizations is likely to be a non-starter.
>>
>>
>>
>>
>>
>>
>>
>> On Tue, May 17, 2016 at 10:30 PM, Kevin Barabash <kevinb at khanacademy.org>
>> wrote:
>>
>>> > I'm thinking, instead, static methods should be used. It would be
>>> more versatile.
>>>
>>> I like the idea of passing both operands as arguments (mainly from an
>>> aesthetics/symmetry point of view), but I can't think of case where it
>>> would be more versatile than instance methods seeing as at least one
>>> argument has to be `this`.  Could you give an example of when this would be
>>> more versatile?
>>>
>>> Since the new syntax is describing what each type should be, maybe we
>>> could leverage existing type syntax from Flow/TypeScript.
>>>
>>> ```js
>>> class Vec2 {
>>>     constructor(x, y) {
>>>         this.x = x
>>>         this.y = y
>>>     }
>>>
>>>     operator+ (x: Vec2, y: Vec2) {
>>>         return new this(x.x + y.x, x.y + y.y)
>>>     }
>>>
>>>     operator+ (x: Vec2, y: number) {
>>>         return new this(x.x + y, x.y + y)
>>>     }
>>>
>>>     operator+= (x: Vec2, y: Vec2) {
>>>         x.x += y.x
>>>         x.y += y.y
>>>     }
>>>
>>>     operator+= (x: Vec2, y: number) {
>>>         x.x += y
>>>         x.y += y
>>>     }
>>>
>>>     // #number += this -> x = x + this
>>>
>>>     operator- (x: Vec2) {
>>>         return new this(-x.x, -x.y)
>>>     }
>>>
>>>     // etc...
>>> }
>>>
>>> class Vec3 {
>>>     // ...
>>>     operator+ (x: Vec3, y: Vec2) {
>>>         return new this(x.x + y.x, x.y + y.y, x.z)
>>>     }
>>>     // etc...
>>> }
>>> ```
>>>
>>>
>>>
>>> On Mon, May 16, 2016 at 12:33 PM, Isiah Meadows <isiahmeadows at gmail.com>
>>> wrote:
>>>
>>>> If both have the operator, the left side would be used (I thought I
>>>> said that, but I may have not). I'm thinking, instead, static methods
>>>> should be used. It would be more versatile.
>>>>
>>>> ```js
>>>> class Vec2 {
>>>>     constructor(x, y) {
>>>>         this.x = x
>>>>         this.y = y
>>>>     }
>>>>
>>>>     // `this` and `Vec2` are interchangeable
>>>>     operator this + this(x, y) {
>>>>         return new this(x.x + y.x, x.y + y.y)
>>>>     }
>>>>
>>>>     operator this + #number(x, y) {
>>>>         return new this(x.x + y, x.y + y)
>>>>     }
>>>>
>>>>     operator this += this(x, y) {
>>>>         x.x += y.x
>>>>         x.y += y.y
>>>>     }
>>>>
>>>>     operator this += #number(x, y) {
>>>>         x.x += y
>>>>         x.y += y
>>>>     }
>>>>
>>>>     // #number += this -> x = x + this
>>>>
>>>>     operator -this(x) {
>>>>         return new this(-x.x, -x.y)
>>>>     }
>>>>
>>>>     // etc...
>>>> }
>>>>
>>>> class Vec3 {
>>>>     // ...
>>>>     operator this + Vec2(x, y) {
>>>>         return new this(x.x + y.x, x.y + y.y, x.z)
>>>>     }
>>>>     // etc...
>>>> }
>>>> ```
>>>>
>>>> A few notes on this:
>>>>
>>>> 1. If an operator doesn't reference `this` or the containing class at
>>>> least once, an early error is thrown.
>>>> 2. To reference a primitive, you use the hash symbol + the typeof
>>>> value. The valid ones include `#string`, `#boolean`, `#number`, `#symbol`,
>>>> `#object`, `#function`, and `#undefined`. If value types with custom
>>>> `typeof` values are introduced, you have to reference the type directly.
>>>> 3. All type references must be either `this`, identifiers, or member
>>>> expressions that do not reference `this`. It is an early error otherwise.
>>>> Member expressions are evaluated at class definition time as well, so that
>>>> can produce visible side effects if a proxy is referenced or a getter is
>>>> called.
>>>> 4. The operators are checked via `instanceof`. This means, for those
>>>> that define operators, the behavior can become visible to previous code if
>>>> the other type specified has a static `Symbol.hasInstance` method.
>>>>
>>>> The reason I provided the `this` alias is for anonymous classes, so you
>>>> can create anonymous objects. It's also helpful in case you have a longer
>>>> class name (possibly by convention) that you now don't have to type out.
>>>>
>>>>
>>>> On Thu, May 12, 2016, 01:17 Kevin Barabash <kevinb at khanacademy.org>
>>>> wrote:
>>>>
>>>>> @Isiah: Great points.  One potential edge case though:
>>>>>
>>>>> ```js
>>>>> class A {
>>>>>     operator+ (other) { }
>>>>> }
>>>>>
>>>>> class B {
>>>>>     operator+ (other) { }
>>>>> }
>>>>>
>>>>> const a = new A();
>>>>> const b = new B();
>>>>> const c = a + b;
>>>>> ```
>>>>>
>>>>> In the case where both the left and right side have `[[OpPlus]]` do we
>>>>> prefer the left side?
>>>>>
>>>>> > But, do we really need operator overloading? A method can be used
>>>>> instead, I think.
>>>>>
>>>>> @Dawid: Suppose I create a class to represent complex numbers that
>>>>> looks like this:
>>>>>
>>>>> ```js
>>>>> class Complex {
>>>>>     constructor(re, im) {
>>>>>          Object.assign({ }, { re, im });
>>>>>     }
>>>>>     add(other) {
>>>>>         return new Complex(this.re + other.re, this.im + other.im);
>>>>>     }
>>>>>     ...
>>>>> }
>>>>> ```
>>>>>
>>>>> I might want to create instance of `Complex` with plain old numbers or
>>>>> I might want to use `BigNumber` instances.
>>>>> Without operator overloading this means that I would have add methods
>>>>> to `Number.prototype` or wrap each number
>>>>> in an object with methods.  Neither of which are particular appealing.
>>>>>
>>>>>
>>>>>
>>>>> On Wed, May 11, 2016 at 1:28 AM, Isiah Meadows <isiahmeadows at gmail.com
>>>>> > wrote:
>>>>>
>>>>>> That's the current state of things. I think the main issue at hand is
>>>>>> ergonomics. Haskell, the MLs, and Swift solved it by allowing inline
>>>>>> functions and operators as functions (that wouldn't work in a dynamic
>>>>>> language). Scala solved it by magic methods for unary operations and the
>>>>>> fact nearly every character is a valid identifier for binary ones (JS can't
>>>>>> use that because of back compat issues). Lua, Ruby, Python, and Kotlin
>>>>>> solved it by using magic methods. C++ solved it with the `operator`
>>>>>> keyword.
>>>>>>
>>>>>> On Wed, May 11, 2016, 03:26 Dawid Szlachta <
>>>>>> dawidmj.szlachta at gmail.com> wrote:
>>>>>>
>>>>>>> But, do we really need operator overloading? A method can be used
>>>>>>> instead, I think.
>>>>>>>
>>>>>>> 2016-05-11 8:53 GMT+02:00 Isiah Meadows <isiahmeadows at gmail.com>:
>>>>>>>
>>>>>>>> Efficiency and optimization. If you're stupid enough to want to
>>>>>>>> violate those priorities in a public API, it's your own fault. But if you
>>>>>>>> want to optimize updating a collection (i.e. zero allocation update for a
>>>>>>>> persistent map) or increment a vector by another without having to create
>>>>>>>> an intermediate vector, you'll want to implement the assignment operator as
>>>>>>>> well as the standard math operator.
>>>>>>>>
>>>>>>>> On Wed, May 11, 2016, 02:46 Jordan Harband <ljharb at gmail.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Why would you ever want to violate the algebraic properties of
>>>>>>>>> operators, such that `a += b` wasn't exactly equivalent to `a = a + b`, `a
>>>>>>>>> *= b` not equivalent to `a = a * b`, etc? I'm quite confident that any
>>>>>>>>> proposal that allowed for that would get tons of pushback.
>>>>>>>>>
>>>>>>>>> On Tue, May 10, 2016 at 11:26 PM, Isiah Meadows <
>>>>>>>>> isiahmeadows at gmail.com> wrote:
>>>>>>>>>
>>>>>>>>>> 1. Yes, they would be inherited, but not on the prototype itself
>>>>>>>>>> (it would technically be parasitic). It would be modeled with internal
>>>>>>>>>> slots, so that the properties are themselves immutable and transparent, so
>>>>>>>>>> the only way to inherit would be via the class syntax or
>>>>>>>>>> `Reflect.construct`. Engines could model this similarly to prototypes
>>>>>>>>>> internally, while still appearing to conform to spec, since there's no
>>>>>>>>>> other way to access the function without explicit reference via a
>>>>>>>>>> decorator. And if it's not decorated, you can transparently fast path the
>>>>>>>>>> calls automatically and optimize the function at compile time for exactly
>>>>>>>>>> the number of arguments (any different is a syntax error, like with getters
>>>>>>>>>> and setters).
>>>>>>>>>>
>>>>>>>>>> 2. I'm intentionally trying to avoid any semantics that would
>>>>>>>>>> rely on adding more values to the global scope. First, it's harder to
>>>>>>>>>> optimize a `hasOwnProperty` check. Second, when you allow properties to be
>>>>>>>>>> dynamically added, you make it impossible to lower `foo + bar` to a single
>>>>>>>>>> instruction if they're both numbers, because someone can change the Number
>>>>>>>>>> prototype to have one of the operators on it, and now, the assumption,
>>>>>>>>>> previously prevalent, is now invalid. Third, we shouldn't need to add 15+
>>>>>>>>>> new symbols to accommodate a simple operation.
>>>>>>>>>>
>>>>>>>>>> 3. If it's pure syntax, you won't have the edge cases of `x += y`
>>>>>>>>>> having to desugar to `x = x[Symbol.assignPlus](y)` and so on. You just look
>>>>>>>>>> for an `[[OpAssignPlus]]` on `x`, and if it exists, call it as `x.[[OpAssignPlus]](y)`.
>>>>>>>>>> Else, you check for `[[OpPlus]]`, and set `x` to `x.[[OpPlus]](y)`. If
>>>>>>>>>> neither exists, you fall back to the old algorithm. This can be easily
>>>>>>>>>> optimized by the fact engines only need to check this if the value is an
>>>>>>>>>> object. Numbers and strings don't have this slot.
>>>>>>>>>>
>>>>>>>>>> Note: If the right side has an operator defined, but the left
>>>>>>>>>> side doesn't, and if the operator checked for isn't an assignment one, the
>>>>>>>>>> right side's operator is checked and called. Or basically, beyond
>>>>>>>>>> assignment, the mere existence of a slot takes precedence over no slot, to
>>>>>>>>>> make transitivity easier with primitives. To clarify, in the below case:
>>>>>>>>>>
>>>>>>>>>> ```js
>>>>>>>>>> class C {
>>>>>>>>>>     constructor(x) { this.x = x }
>>>>>>>>>>     operator +(x) {
>>>>>>>>>>         if (x instanceof C) {
>>>>>>>>>>             return this + x.x * 2
>>>>>>>>>>         }
>>>>>>>>>>         return this.x + x
>>>>>>>>>>     }
>>>>>>>>>> }
>>>>>>>>>>
>>>>>>>>>> assert(new C(1) + 1 === 1 +1)
>>>>>>>>>> assert(1 + new C(1) === 1 + 1)
>>>>>>>>>> assert(new C(1) + new C(2) === 1 + 2*2)
>>>>>>>>>> assert(new C(2) + new C(1) === 2 + 1*2)
>>>>>>>>>> ```
>>>>>>>>>>
>>>>>>>>>> On Wed, May 11, 2016, 01:27 Kevin Barabash <
>>>>>>>>>> kevinb at khanacademy.org> wrote:
>>>>>>>>>>
>>>>>>>>>>> > I would prefer syntax + internal slots, since you'll know at
>>>>>>>>>>> creation time whether the object has overloaded
>>>>>>>>>>> > operators. It's much simpler for the engine to figure out, and
>>>>>>>>>>> it's more performant because you only need to
>>>>>>>>>>> > check one thing instead of worrying about inheritance, own
>>>>>>>>>>> properties, etc.
>>>>>>>>>>>
>>>>>>>>>>> Will operators defined on a class work with instances of a
>>>>>>>>>>> subclass?
>>>>>>>>>>>
>>>>>>>>>>> > Could += be a special case? i.e.,
>>>>>>>>>>>
>>>>>>>>>>> For sure.  We could define `Symbol.assignPlus`,
>>>>>>>>>>> `Symbol.assignTimes`, etc. with `u += v;` desugaring to `u =
>>>>>>>>>>> u[Symbol.assignPlus](v)`.  The reason why we can't do something do
>>>>>>>>>>> `u[Symbol.assignPlus](v)` is that there's no way to define a method on
>>>>>>>>>>> Number, String, etc. that would reassign their value.
>>>>>>>>>>>
>>>>>>>>>>> > it appears to me that overloading an operator multiple times
>>>>>>>>>>> (e. g. unary/binary plus operator) might become
>>>>>>>>>>> > painful, assuming that the semantics follow the same variadic
>>>>>>>>>>> approach that regular functions do.
>>>>>>>>>>>
>>>>>>>>>>> Another pain point is handling cases where you want one class to
>>>>>>>>>>> interoperate with another.  In one of the example above methods are defined
>>>>>>>>>>> that allow `Point`s and `Number`s to be added to each other.  In order to
>>>>>>>>>>> maintain the commutativity of `+` we need to define `operator+` /
>>>>>>>>>>> `[Symbol.add]` methods on both `Point` and `Number`.  One potential
>>>>>>>>>>> solution to this problem is create `Symbol.plusRight`, `Symbol.timesRight`
>>>>>>>>>>> for all of the commutative/symmetric operators.
>>>>>>>>>>>
>>>>>>>>>>> I feel like this ends up making things more complex because
>>>>>>>>>>> there are more methods to implement and the methods have to be more complex
>>>>>>>>>>> b/c they have to do type checking when overloaded.
>>>>>>>>>>>
>>>>>>>>>>> Maybe `operator+` could work like the `@operator` decorator by
>>>>>>>>>>> calling `Function.defineOperator` behind the scenes.  In this situation,
>>>>>>>>>>> instead of methods being added to classes, the `Function` object has
>>>>>>>>>>> well-defined methods that look up the correct function to call based on the
>>>>>>>>>>> argument types.  `u + v` desugars to `Function[Symbol.plus](u, v)`.  This
>>>>>>>>>>> is definitely slower than internal slots, but if we're doing runtime type
>>>>>>>>>>> checking in the method we may as well have it be automatic.  My hope is to
>>>>>>>>>>> eventually use static typing (flow b/c I'm using babel) to remove the
>>>>>>>>>>> lookup cost.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On Tue, May 10, 2016 at 7:07 PM, Isiah Meadows <
>>>>>>>>>>> isiahmeadows at gmail.com> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> You're correct in that the operator doesn't do any type
>>>>>>>>>>>> checking (it dispatches from its first argument, but that's just
>>>>>>>>>>>> traditional OO).
>>>>>>>>>>>>
>>>>>>>>>>>> On Tue, May 10, 2016, 20:28 kdex <kdex at kdex.de> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> @Isiah: Comparing your syntax proposal to
>>>>>>>>>>>>> `Function.defineOperator`, it appears to me that
>>>>>>>>>>>>> overloading an operator multiple times (e. g. unary/binary
>>>>>>>>>>>>> plus operator) might become painful,
>>>>>>>>>>>>> assuming that the semantics follow the same variadic approach
>>>>>>>>>>>>> that regular functions do.
>>>>>>>>>>>>>
>>>>>>>>>>>>> That is, of course, unless you intend to handle all operator
>>>>>>>>>>>>> overloads in a single `operator +(...args) {}`
>>>>>>>>>>>>> definition. But then again, something like
>>>>>>>>>>>>> `Function.defineOperator` seems cleaner and suggests implicit
>>>>>>>>>>>>> (optional?) type checks with its second argument.
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Dienstag, 10. Mai 2016 15:25:32 CEST Isiah Meadows wrote:
>>>>>>>>>>>>> > Here's my thought, if we go with syntax.
>>>>>>>>>>>>> >
>>>>>>>>>>>>> > ```js
>>>>>>>>>>>>> > class Point {
>>>>>>>>>>>>> >     // constructor, etc.
>>>>>>>>>>>>> >
>>>>>>>>>>>>> >     operator +(other) {
>>>>>>>>>>>>> >         assert(other instanceof Point)
>>>>>>>>>>>>> >         return new Point(
>>>>>>>>>>>>> >             this.x + other.x,
>>>>>>>>>>>>> >             this.y + other.y)
>>>>>>>>>>>>> >     }
>>>>>>>>>>>>> >
>>>>>>>>>>>>> >     operator +=(other) {
>>>>>>>>>>>>> >         assert(other instanceof Point)
>>>>>>>>>>>>> >         this.x += other.x
>>>>>>>>>>>>> >         this.y += other.y
>>>>>>>>>>>>> >     }
>>>>>>>>>>>>> > }
>>>>>>>>>>>>> > ```
>>>>>>>>>>>>> >
>>>>>>>>>>>>> > On Tue, May 10, 2016, 11:16 Brian Barnes <ggadwa at charter.net>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>> >
>>>>>>>>>>>>> > > A note on this from somebody who's entire existence seems
>>>>>>>>>>>>> dedicated to
>>>>>>>>>>>>> > > stopping as much stuff as possible from getting GC'd, the
>>>>>>>>>>>>> example below:
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > >  >const u = new Point(5, 10);
>>>>>>>>>>>>> > >  >const v = new Point(1, -2);
>>>>>>>>>>>>> > >  >
>>>>>>>>>>>>> > >  >const w = u + v;  // desugars to u[Symbol.add](v)
>>>>>>>>>>>>> > >  >console.log(w);   // { x: 6, y: 8 };
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > Could += be a special case?  i.e.,
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > u+=v;
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > would call:
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > Class Point { ... other stuff ...
>>>>>>>>>>>>> > > [whatever the syntax is](pt)
>>>>>>>>>>>>> > > {
>>>>>>>>>>>>> > > this.x+=pt.x;
>>>>>>>>>>>>> > > this.y+=pt.y;
>>>>>>>>>>>>> > > }
>>>>>>>>>>>>> > > }
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > instead of desugaring to:
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > u=u+v;          // which would cause the creation of an
>>>>>>>>>>>>> object and
>>>>>>>>>>>>> > >                 // leave the other to be collected
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > For all I know, += might be doing such anyway in some
>>>>>>>>>>>>> engines, but for
>>>>>>>>>>>>> > > my stuff which is a lot of 3D math that could be a
>>>>>>>>>>>>> performance killer.
>>>>>>>>>>>>> > > It would be nice to be able to just add points and such,
>>>>>>>>>>>>> as long as the
>>>>>>>>>>>>> > > overhead is negligible.
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > [>] Brian
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> > > On 5/10/2016 10:52 AM, Isiah Meadows wrote:
>>>>>>>>>>>>> > > > I would prefer syntax + internal slots, since you'll
>>>>>>>>>>>>> know at creation
>>>>>>>>>>>>> > > > time whether the object has overloaded operators. It's
>>>>>>>>>>>>> much simpler for
>>>>>>>>>>>>> > > > the engine to figure out, and it's more performant
>>>>>>>>>>>>> because you only need
>>>>>>>>>>>>> > > > to check one thing instead of worrying about
>>>>>>>>>>>>> inheritance, own
>>>>>>>>>>>>> > > > properties, etc.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > > Also, it would be IMHO easier to read than a symbol (the
>>>>>>>>>>>>> computed
>>>>>>>>>>>>> > > > property syntax is ugly IMO). Using a different concept
>>>>>>>>>>>>> than symbols
>>>>>>>>>>>>> > > > would also fit better with value types whenever any of
>>>>>>>>>>>>> those proposals
>>>>>>>>>>>>> > > > make it into the language (either the struct or special
>>>>>>>>>>>>> syntax).
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > > On Tue, May 10, 2016, 04:03 G. Kay Lee
>>>>>>>>>>>>> > > > <balancetraveller+es-discuss at gmail.com
>>>>>>>>>>>>> > > > <mailto:balancetraveller%2Bes-discuss at gmail.com>> wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >     Yes, I think exposing operators through well-known
>>>>>>>>>>>>> symbols is an
>>>>>>>>>>>>> > > >     interesting idea worthy of more exploration because
>>>>>>>>>>>>> it's precisely
>>>>>>>>>>>>> > > >     the purpose of well-known symbols to expose and
>>>>>>>>>>>>> allow manipulation
>>>>>>>>>>>>> > > >     to previously inaccessible internal language
>>>>>>>>>>>>> behaviors.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >     On Tue, May 10, 2016 at 1:59 PM, Kevin Barabash
>>>>>>>>>>>>> > > >     <kevinb at khanacademy.org <mailto:
>>>>>>>>>>>>> kevinb at khanacademy.org>> wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         > And remember that decorators are essentially
>>>>>>>>>>>>> just a syntax to
>>>>>>>>>>>>> > > >         apply functions to objects/classes at design
>>>>>>>>>>>>> time, so what
>>>>>>>>>>>>> > > >         you're proposing is essentially some new global
>>>>>>>>>>>>> function, which
>>>>>>>>>>>>> > > >         is going against the current trend and effort to
>>>>>>>>>>>>> better
>>>>>>>>>>>>> > > >         modularize/namespace all these utility
>>>>>>>>>>>>> functions/methods.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         That's a really good point.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         > It has been mentioned and discussed in
>>>>>>>>>>>>> numerous places over the
>>>>>>>>>>>>> > > >         years, you can find more info on this with some
>>>>>>>>>>>>> casual googling.
>>>>>>>>>>>>> > > >         For example:
>>>>>>>>>>>>> https://news.ycombinator.com/item?id=2983420
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         Thanks for the link.  I played around with
>>>>>>>>>>>>> sweet.js a bit over
>>>>>>>>>>>>> > > >         the weekend.  Using macros should work if we
>>>>>>>>>>>>> went with Python
>>>>>>>>>>>>> > > >         style operator overloading.  Instead of defining
>>>>>>>>>>>>> methods like
>>>>>>>>>>>>> > > >         _ADD_, _SUB_ etc. we could create some
>>>>>>>>>>>>> well-known symbols, maybe
>>>>>>>>>>>>> > > >         Symbol.plus, Symbol.times, etc.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         ```
>>>>>>>>>>>>> > > >         class Point {
>>>>>>>>>>>>> > > >           constructor(x, y) {
>>>>>>>>>>>>> > > >             Object.assign(this, {x, y});
>>>>>>>>>>>>> > > >           }
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >           [Symbol.add](other) {
>>>>>>>>>>>>> > > >             return new Point(this.x + other.x, this.y +
>>>>>>>>>>>>> other.y);
>>>>>>>>>>>>> > > >           }
>>>>>>>>>>>>> > > >         }
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         const u = new Point(5, 10);
>>>>>>>>>>>>> > > >         const v = new Point(1, -2);
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         const w = u + v;  // desugars to u[Symbol.add](v)
>>>>>>>>>>>>> > > >         console.log(w);   // { x: 6, y: 8 };
>>>>>>>>>>>>> > > >         ```
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         This would require default implementations to be
>>>>>>>>>>>>> defined on
>>>>>>>>>>>>> > > >         Object.prototype for Symbol.plus, Symbol.times,
>>>>>>>>>>>>> etc.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         On Sun, May 8, 2016 at 10:38 PM, G. Kay Lee
>>>>>>>>>>>>> > > >         <balancetraveller+es-discuss at gmail.com
>>>>>>>>>>>>> > > >         <mailto:balancetraveller+es-discuss at gmail.com>>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >             > Why not? The standard defines well-known
>>>>>>>>>>>>> symbols. Maybe
>>>>>>>>>>>>> > > `@operator` could be a well known decorator (assuming
>>>>>>>>>>>>> decorators get
>>>>>>>>>>>>> > > approved).
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >             Well... you make something into the standard
>>>>>>>>>>>>> with proposals,
>>>>>>>>>>>>> > > >             not why-nots, so in order to make that
>>>>>>>>>>>>> happen you need to
>>>>>>>>>>>>> > > >             draft another proposal for well-known
>>>>>>>>>>>>> decorators. And
>>>>>>>>>>>>> > > >             remember that decorators are essentially
>>>>>>>>>>>>> just a syntax to
>>>>>>>>>>>>> > > >             apply functions to objects/classes at design
>>>>>>>>>>>>> time, so what
>>>>>>>>>>>>> > > >             you're proposing is essentially some new
>>>>>>>>>>>>> global function,
>>>>>>>>>>>>> > > >             which is going against the current trend and
>>>>>>>>>>>>> effort to
>>>>>>>>>>>>> > > >             better modularize/namespace all these utility
>>>>>>>>>>>>> > > >             functions/methods. And maybe a new mechanism
>>>>>>>>>>>>> could be
>>>>>>>>>>>>> > > >             drafted for these new well-known decorators,
>>>>>>>>>>>>> so that we can
>>>>>>>>>>>>> > > >             hide these new functions somewhere... but by
>>>>>>>>>>>>> now I hope it's
>>>>>>>>>>>>> > > >             becoming clear that it's introducing way too
>>>>>>>>>>>>> much new
>>>>>>>>>>>>> > > >             surface area for the language in exchange
>>>>>>>>>>>>> for one small
>>>>>>>>>>>>> > > feature.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >             > I haven't seen any proposals for macros,
>>>>>>>>>>>>> could you post a
>>>>>>>>>>>>> > > link?
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >             It has been mentioned and discussed in
>>>>>>>>>>>>> numerous places over
>>>>>>>>>>>>> > > >             the years, you can find more info on this
>>>>>>>>>>>>> with some casual
>>>>>>>>>>>>> > > >             googling. For example:
>>>>>>>>>>>>> > > >             https://news.ycombinator.com/item?id=2983420
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >             On Sun, May 8, 2016 at 2:51 PM, Kevin
>>>>>>>>>>>>> Barabash
>>>>>>>>>>>>> > > >             <kevinb at khanacademy.org <mailto:
>>>>>>>>>>>>> kevinb at khanacademy.org>>
>>>>>>>>>>>>> > > wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 I should update the demo code to show
>>>>>>>>>>>>> the `@operator`
>>>>>>>>>>>>> > > >                 decorator in addition to
>>>>>>>>>>>>> `Function.defineOperator`.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 Initially I started out with just the
>>>>>>>>>>>>> `@operator`
>>>>>>>>>>>>> > > >                 decorator, but that meant that each
>>>>>>>>>>>>> class would have to
>>>>>>>>>>>>> > > >                 have knowledge of each of the classes it
>>>>>>>>>>>>> might want to
>>>>>>>>>>>>> > > >                 interact with before hand.  Having a
>>>>>>>>>>>>> separate
>>>>>>>>>>>>> > > >                 `defineOperator` function avoids this
>>>>>>>>>>>>> situation.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 It means that prototype style classes
>>>>>>>>>>>>> must be converted
>>>>>>>>>>>>> > > >                 to the new class syntax before operator
>>>>>>>>>>>>> overloading
>>>>>>>>>>>>> > > >                 could be used.  Lastly, there may be
>>>>>>>>>>>>> some cases where it
>>>>>>>>>>>>> > > >                 makes sense to overload operators with
>>>>>>>>>>>>> existing 3rd
>>>>>>>>>>>>> > > >                 party code or built-in classes, e.g.
>>>>>>>>>>>>> adding set
>>>>>>>>>>>>> > > >                 operations to Set using operator
>>>>>>>>>>>>> overloading.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 > It's also apparent that the `@operator
>>>>>>>>>>>>> decorator` part
>>>>>>>>>>>>> > > >                 of the proposal is an effort trying to
>>>>>>>>>>>>> address this
>>>>>>>>>>>>> > > >                 issue, but it really is not the
>>>>>>>>>>>>> responsibility of the
>>>>>>>>>>>>> > > >                 standard to try to define such a thing.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 Why not?  The standard defines
>>>>>>>>>>>>> well-known symbols.
>>>>>>>>>>>>> > > >                 Maybe `@operator` could be a well known
>>>>>>>>>>>>> decorator
>>>>>>>>>>>>> > > >                 (assuming decorators get approved).
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 Slide 15
>>>>>>>>>>>>> > > >                 from
>>>>>>>>>>>>> http://www.slideshare.net/BrendanEich/js-resp shows
>>>>>>>>>>>>> > > >                 syntax for defining operators in value
>>>>>>>>>>>>> types which could
>>>>>>>>>>>>> > > >                 be adapted as follows for regular
>>>>>>>>>>>>> classes:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 ```
>>>>>>>>>>>>> > > >                 class Point {
>>>>>>>>>>>>> > > >                    constructor(x, y) {
>>>>>>>>>>>>> > > >                        this.x = +x;
>>>>>>>>>>>>> > > >                        this.y = +y;
>>>>>>>>>>>>> > > >                    }
>>>>>>>>>>>>> > > >                    Point + Number (a, b) {
>>>>>>>>>>>>> > > >                        return new Point(a.x + b, a.y +
>>>>>>>>>>>>> b);
>>>>>>>>>>>>> > > >                    }
>>>>>>>>>>>>> > > >                    Number + Point (a, b) {
>>>>>>>>>>>>> > > >                        return new Point(a + b.x, a +
>>>>>>>>>>>>> b.y);
>>>>>>>>>>>>> > > >                    }
>>>>>>>>>>>>> > > >                    Point + Point (a, b) {
>>>>>>>>>>>>> > > >                        return new Point(a.x + b.x, a.y +
>>>>>>>>>>>>> b.y);
>>>>>>>>>>>>> > > >                    }
>>>>>>>>>>>>> > > >                 }
>>>>>>>>>>>>> > > >                 ```
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 Having to define `+` twice for `Point +
>>>>>>>>>>>>> Number` and
>>>>>>>>>>>>> > > >                 `Number + Point` seems like busy work,
>>>>>>>>>>>>> but maybe it's
>>>>>>>>>>>>> > > >                 better to be explicit.  What are you
>>>>>>>>>>>>> thoughts about this
>>>>>>>>>>>>> > > >                 syntax?
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 > Another thing is that, IMHO, currently
>>>>>>>>>>>>> there are too
>>>>>>>>>>>>> > > >                 much quirks/conventions in the proposal
>>>>>>>>>>>>> that feel
>>>>>>>>>>>>> > > >                 non-evident and non-flexible which is
>>>>>>>>>>>>> destined to trip
>>>>>>>>>>>>> > > >                 people over from time to time. It would
>>>>>>>>>>>>> be great to make
>>>>>>>>>>>>> > > >                 a proposal that's simple and don't
>>>>>>>>>>>>> include too much
>>>>>>>>>>>>> > > >                 assumptions.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 Could you elaborator what
>>>>>>>>>>>>> quirks/conventions might trip
>>>>>>>>>>>>> > > >                 people up?
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 > Finally, I'm not sure about the
>>>>>>>>>>>>> current status of
>>>>>>>>>>>>> > > >                 macros, but last I heard of it, they say
>>>>>>>>>>>>> it's going to
>>>>>>>>>>>>> > > >                 make its way into the standard pretty
>>>>>>>>>>>>> soon (TM), and
>>>>>>>>>>>>> > > >                 macros can do much of the things
>>>>>>>>>>>>> overloading could, and
>>>>>>>>>>>>> > > >                 much more.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 I haven't seen any proposals for macros,
>>>>>>>>>>>>> could you post
>>>>>>>>>>>>> > > >                 a link?
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                 On Sat, May 7, 2016 at 9:55 PM, G. Kay
>>>>>>>>>>>>> Lee
>>>>>>>>>>>>> > > >                 <balancetraveller+es-discuss at gmail.com
>>>>>>>>>>>>> > > >                 <mailto:
>>>>>>>>>>>>> balancetraveller+es-discuss at gmail.com>> wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     I'd say it's way too early to ask
>>>>>>>>>>>>> for a champion on
>>>>>>>>>>>>> > > >                     this because just a quick skimming
>>>>>>>>>>>>> revealed a lot of
>>>>>>>>>>>>> > > >                     places that didn't add up. For
>>>>>>>>>>>>> example, the proposal
>>>>>>>>>>>>> > > >                     suggested that overloading is
>>>>>>>>>>>>> primarily targeted at
>>>>>>>>>>>>> > > >                     making it easier to work with
>>>>>>>>>>>>> user-defined classes,
>>>>>>>>>>>>> > > >                     but curiously a
>>>>>>>>>>>>> `Function.defineOperator()` method
>>>>>>>>>>>>> > > >                     is proposed instead of some syntax
>>>>>>>>>>>>> that feels more
>>>>>>>>>>>>> > > >                     tightly integrated with the class
>>>>>>>>>>>>> definition syntax.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     ```
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     class Point {
>>>>>>>>>>>>> > > >                         constructor(x, y) {
>>>>>>>>>>>>> > > >                             Object.assign(this, { x, y
>>>>>>>>>>>>> });
>>>>>>>>>>>>> > > >                         }
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                         toString() {
>>>>>>>>>>>>> > > >                             return `(${this.x},
>>>>>>>>>>>>> ${this.y})`;
>>>>>>>>>>>>> > > >                         }
>>>>>>>>>>>>> > > >                     }
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     Function.defineOperator('+', [Point,
>>>>>>>>>>>>> Point], (a, b)
>>>>>>>>>>>>> > > => new Point(a.x + b.x, a.y + b.y));
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     ```
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     The demo code made this flaw evident
>>>>>>>>>>>>> - it looks like
>>>>>>>>>>>>> > > >                     a giant step backward to define an
>>>>>>>>>>>>> instance method
>>>>>>>>>>>>> > > >                     like this, don't you agree?
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     It's also apparent that the
>>>>>>>>>>>>> `@operator decorator`
>>>>>>>>>>>>> > > >                     part of the proposal is an effort
>>>>>>>>>>>>> trying to address
>>>>>>>>>>>>> > > >                     this issue, but it really is not the
>>>>>>>>>>>>> responsibility
>>>>>>>>>>>>> > > >                     of the standard to try to define
>>>>>>>>>>>>> such a thing.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     What I'd suggest is that perhaps you
>>>>>>>>>>>>> should rethink
>>>>>>>>>>>>> > > >                     your proposed syntax and redesign it
>>>>>>>>>>>>> to become an
>>>>>>>>>>>>> > > >                     extension of the ES6 class
>>>>>>>>>>>>> definition syntax.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     Another thing is that, IMHO,
>>>>>>>>>>>>> currently there are too
>>>>>>>>>>>>> > > >                     much quirks/conventions in the
>>>>>>>>>>>>> proposal that feel
>>>>>>>>>>>>> > > >                     non-evident and non-flexible which
>>>>>>>>>>>>> is destined to
>>>>>>>>>>>>> > > >                     trip people over from time to time.
>>>>>>>>>>>>> It would be
>>>>>>>>>>>>> > > >                     great to make a proposal that's
>>>>>>>>>>>>> simple and don't
>>>>>>>>>>>>> > > >                     include too much assumptions.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     Finally, I'm not sure about the
>>>>>>>>>>>>> current status of
>>>>>>>>>>>>> > > >                     macros, but last I heard of it, they
>>>>>>>>>>>>> say it's going
>>>>>>>>>>>>> > > >                     to make its way into the standard
>>>>>>>>>>>>> pretty soon (TM),
>>>>>>>>>>>>> > > >                     and macros can do much of the things
>>>>>>>>>>>>> overloading
>>>>>>>>>>>>> > > >                     could, and much more.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                     On Sun, May 8, 2016 at 8:51 AM,
>>>>>>>>>>>>> Kevin Barabash
>>>>>>>>>>>>> > > >                     <kevinb at khanacademy.org
>>>>>>>>>>>>> > > >                     <mailto:kevinb at khanacademy.org>>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                         I forgot to mention in my last
>>>>>>>>>>>>> email that I'm
>>>>>>>>>>>>> > > >                         looking for a champion for this
>>>>>>>>>>>>> proposal.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                         On Sat, May 7, 2016 at 5:24 PM,
>>>>>>>>>>>>> Kevin Barabash
>>>>>>>>>>>>> > > >                         <kevinb at khanacademy.org
>>>>>>>>>>>>> > > >                         <mailto:kevinb at khanacademy.org>>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             Hi everyone,
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             I've been working on
>>>>>>>>>>>>> implementing operator
>>>>>>>>>>>>> > > >                             overloading and would like
>>>>>>>>>>>>> to submit a
>>>>>>>>>>>>> > > proposal.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             I think operator overloading
>>>>>>>>>>>>> would be a
>>>>>>>>>>>>> > > >                             useful addition to the
>>>>>>>>>>>>> language.  In
>>>>>>>>>>>>> > > >                             particular I think it would
>>>>>>>>>>>>> be useful for
>>>>>>>>>>>>> > > >                             defining operations on
>>>>>>>>>>>>> common mathematical
>>>>>>>>>>>>> > > >                             object types such as complex
>>>>>>>>>>>>> numbers,
>>>>>>>>>>>>> > > >                             vectors, matrices, and sets.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             I've create a working
>>>>>>>>>>>>> prototype that
>>>>>>>>>>>>> > > >                             consists of:
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                               * babel plugin that
>>>>>>>>>>>>> rewrites operators as
>>>>>>>>>>>>> > > >                                 function calls
>>>>>>>>>>>>> > > >                               * a polyfill which defines
>>>>>>>>>>>>> these functions
>>>>>>>>>>>>> > > >                                 and which call the
>>>>>>>>>>>>> correct
>>>>>>>>>>>>> > > >                                 argument-specific
>>>>>>>>>>>>> function based on the
>>>>>>>>>>>>> > > >                                 arguments' prototypes
>>>>>>>>>>>>> > > >                               * Function.defineOperator
>>>>>>>>>>>>> which can be
>>>>>>>>>>>>> > > >                                 used to define which
>>>>>>>>>>>>> function an
>>>>>>>>>>>>> > > >                                 operator should use for
>>>>>>>>>>>>> the specified
>>>>>>>>>>>>> > > types
>>>>>>>>>>>>> > > >                               * "use overloading"
>>>>>>>>>>>>> directive which allows
>>>>>>>>>>>>> > > >                                 users to opt-in
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             More details can be found
>>>>>>>>>>>>> > > >                             at
>>>>>>>>>>>>> > > https://github.com/kevinbarabash/operator-overloading.
>>>>>>>>>>>>> > > >                             The babel plugin can be found
>>>>>>>>>>>>> > > >                             at
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> https://github.com/kevinbarabash/babel-plugin-operator-overloading
>>>>>>>>>>>>> .
>>>>>>>>>>>>> > > >                             I also have a demo project at
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > https://github.com/kevinbarabash/operator-overloading-demo
>>>>>>>>>>>>> .
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             The design was inspired by
>>>>>>>>>>>>> some of the
>>>>>>>>>>>>> > > >                             slides from
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > http://www.slideshare.net/BrendanEich/js-resp.
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >                             – Kevin
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>>  _______________________________________________
>>>>>>>>>>>>> > > >                         es-discuss mailing list
>>>>>>>>>>>>> > > >                         es-discuss at mozilla.org
>>>>>>>>>>>>> > > >                         <mailto:es-discuss at mozilla.org>
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>>  _______________________________________________
>>>>>>>>>>>>> > > >                     es-discuss mailing list
>>>>>>>>>>>>> > > >                     es-discuss at mozilla.org <mailto:
>>>>>>>>>>>>> > > es-discuss at mozilla.org>
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>>  _______________________________________________
>>>>>>>>>>>>> > > >                 es-discuss mailing list
>>>>>>>>>>>>> > > >                 es-discuss at mozilla.org <mailto:
>>>>>>>>>>>>> es-discuss at mozilla.org>
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>>  _______________________________________________
>>>>>>>>>>>>> > > >             es-discuss mailing list
>>>>>>>>>>>>> > > >             es-discuss at mozilla.org <mailto:
>>>>>>>>>>>>> es-discuss at mozilla.org>
>>>>>>>>>>>>> > > >             https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >         _______________________________________________
>>>>>>>>>>>>> > > >         es-discuss mailing list
>>>>>>>>>>>>> > > >         es-discuss at mozilla.org <mailto:
>>>>>>>>>>>>> es-discuss at mozilla.org>
>>>>>>>>>>>>> > > >         https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >     _______________________________________________
>>>>>>>>>>>>> > > >     es-discuss mailing list
>>>>>>>>>>>>> > > >     es-discuss at mozilla.org <mailto:
>>>>>>>>>>>>> es-discuss at mozilla.org>
>>>>>>>>>>>>> > > >     https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > > _______________________________________________
>>>>>>>>>>>>> > > > es-discuss mailing list
>>>>>>>>>>>>> > > > es-discuss at mozilla.org
>>>>>>>>>>>>> > > > https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > > >
>>>>>>>>>>>>> > > _______________________________________________
>>>>>>>>>>>>> > > es-discuss mailing list
>>>>>>>>>>>>> > > es-discuss at mozilla.org
>>>>>>>>>>>>> > > https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>> > >
>>>>>>>>>>>>> >
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>> es-discuss mailing list
>>>>>>>>>>>> es-discuss at mozilla.org
>>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>> _______________________________________________
>>>>>>>>>>> es-discuss mailing list
>>>>>>>>>>> es-discuss at mozilla.org
>>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> _______________________________________________
>>>>>>>>>> es-discuss mailing list
>>>>>>>>>> es-discuss at mozilla.org
>>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> es-discuss mailing list
>>>>>>>> es-discuss at mozilla.org
>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>> _______________________________________________
>>>>>> es-discuss mailing list
>>>>>> es-discuss at mozilla.org
>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>
>>>>>>
>>>>> _______________________________________________
>>>>> es-discuss mailing list
>>>>> es-discuss at mozilla.org
>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>
>>>>
>>>
>>> _______________________________________________
>>> 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/20160520/8cd3c092/attachment-0001.html>


More information about the es-discuss mailing list