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 <ljh...@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 <isiahmead...@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 <kev...@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 <isiahmead...@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 <k...@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 <gga...@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-disc...@gmail.com >>>>> > > > <mailto:balancetraveller%2bes-disc...@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 >>>>> > > > <kev...@khanacademy.org <mailto:kev...@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-disc...@gmail.com >>>>> > > > <mailto:balancetraveller+es-disc...@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 >>>>> > > > <kev...@khanacademy.org <mailto: >>>>> kev...@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-disc...@gmail.com >>>>> > > > <mailto:balancetraveller+es-disc...@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 >>>>> > > > <kev...@khanacademy.org >>>>> > > > <mailto:kev...@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 >>>>> > > > <kev...@khanacademy.org >>>>> > > > <mailto:kev...@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@mozilla.org >>>>> > > > <mailto:es-discuss@mozilla.org> >>>>> > > > >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > > >>>>> > > > >>>>> > > > >>>>> _______________________________________________ >>>>> > > > es-discuss mailing list >>>>> > > > es-discuss@mozilla.org <mailto: >>>>> > > es-discuss@mozilla.org> >>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > > >>>>> > > > >>>>> > > > _______________________________________________ >>>>> > > > es-discuss mailing list >>>>> > > > es-discuss@mozilla.org <mailto: >>>>> es-discuss@mozilla.org> >>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > > >>>>> > > > >>>>> > > > _______________________________________________ >>>>> > > > es-discuss mailing list >>>>> > > > es-discuss@mozilla.org <mailto: >>>>> es-discuss@mozilla.org> >>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > > >>>>> > > > >>>>> > > > _______________________________________________ >>>>> > > > es-discuss mailing list >>>>> > > > es-discuss@mozilla.org <mailto:es-discuss@mozilla.org> >>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > > >>>>> > > > _______________________________________________ >>>>> > > > es-discuss mailing list >>>>> > > > es-discuss@mozilla.org <mailto:es-discuss@mozilla.org> >>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > > >>>>> > > > >>>>> > > > _______________________________________________ >>>>> > > > es-discuss mailing list >>>>> > > > es-discuss@mozilla.org >>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > > >>>>> > > _______________________________________________ >>>>> > > es-discuss mailing list >>>>> > > es-discuss@mozilla.org >>>>> > > https://mail.mozilla.org/listinfo/es-discuss >>>>> > > >>>>> > >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss@mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> >
_______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss