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 <[email protected]>: > 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 <[email protected]> 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 <[email protected]> >> 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 <[email protected]> >>> 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 <[email protected]> >>>> 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 <[email protected]> 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 <[email protected]> >>>>>> 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 >>>>>> > > > <[email protected] >>>>>> > > > <mailto:balancetraveller%[email protected]>> 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 >>>>>> > > > <[email protected] <mailto:[email protected]>> >>>>>> 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 >>>>>> > > > <[email protected] >>>>>> > > > <mailto:[email protected]>> 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 >>>>>> > > > <[email protected] <mailto: >>>>>> [email protected]>> >>>>>> > > 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 >>>>>> > > > <[email protected] >>>>>> > > > <mailto:[email protected]>> >>>>>> 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 >>>>>> > > > <[email protected] >>>>>> > > > <mailto:[email protected]>> 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 >>>>>> > > > <[email protected] >>>>>> > > > <mailto:[email protected]>> 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 >>>>>> > > > [email protected] >>>>>> > > > <mailto:[email protected]> >>>>>> > > > >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > > >>>>>> > > > >>>>>> > > > >>>>>> _______________________________________________ >>>>>> > > > es-discuss mailing list >>>>>> > > > [email protected] <mailto: >>>>>> > > [email protected]> >>>>>> > > > >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > > >>>>>> > > > >>>>>> > > > _______________________________________________ >>>>>> > > > es-discuss mailing list >>>>>> > > > [email protected] <mailto: >>>>>> [email protected]> >>>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > > >>>>>> > > > >>>>>> > > > _______________________________________________ >>>>>> > > > es-discuss mailing list >>>>>> > > > [email protected] <mailto: >>>>>> [email protected]> >>>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > > >>>>>> > > > >>>>>> > > > _______________________________________________ >>>>>> > > > es-discuss mailing list >>>>>> > > > [email protected] <mailto:[email protected]> >>>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > > >>>>>> > > > _______________________________________________ >>>>>> > > > es-discuss mailing list >>>>>> > > > [email protected] <mailto:[email protected]> >>>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > > >>>>>> > > > >>>>>> > > > _______________________________________________ >>>>>> > > > es-discuss mailing list >>>>>> > > > [email protected] >>>>>> > > > https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > > >>>>>> > > _______________________________________________ >>>>>> > > es-discuss mailing list >>>>>> > > [email protected] >>>>>> > > https://mail.mozilla.org/listinfo/es-discuss >>>>>> > > >>>>>> > >>>>>> >>>>> >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> [email protected] >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> [email protected] >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> [email protected] >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> > _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss > >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

