Re: Globalization API discussion
On Nov 20, 2011, at 1:18 PM, David Herman wrote: >> I would not add more implicit magic to JS. E4X had junk like this in it, >> which only ever concealed bugs. > > I'm of two minds about this. In the abstract, I agree with Brendan; fail-soft > conceals bugs. But in reality, our destructuring logic is incredible > fail-soft. Hardly anything in destructuring is treated as an error. And the > syntax really *wants* to match the common pattern. So I'm torn. 1. Failing to write that means a destructuring parameter with default values within the pattern cannot be observed via arguments[i] as undefined (or null?). If missing, the undefined will be replaced by a fresh object. This isn't consistent with any other combination of destructuring parameters and parameter default values. 2. If a function wants to throw an error for a missing options parameter, it has no way of telling other than arguments.length checking. 3. It's not hard to write " = {}". /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API: Objects needed?
When a caller of the Globalization API requests a locale or parameter combination that's valid but that the implementation doesn't support, then the implementation falls back to something it does support. The resolvedOptions accessor property of the constructed object provides information on what the implementation came up with, so that the caller can decide whether the fallback is acceptable or whether it wants to use alternative solutions. Examples: - A caller requests a date format for Spanish in Guatemala, and the implementation doesn't have that. The implementation might fall back to a generic Spanish (probably for Spain), or to the Spanish of big neighbor Mexico, or, if it runs on a budget cell phone designed for India and doesn't have any Spanish, even to Hindi. The caller might decide that any Spanish is OK as long as the month is spelled out (users shouldn't have to guess between day/month and month/day formats), but that Hindi needs to be worked around by loading up another date formatting library that does support Spanish. - A application for Islamic prayer times requests the Islamic calendar; if the implementation offers Gregorian instead, the application may load a library that does support Islamic. Norbert On Nov 20, 2011, at 9:59 , Brendan Eich wrote: > On Nov 19, 2011, at 7:27 PM, Norbert Lindenberg wrote: > 2.a. Find out if there were fallbacks through object state >>> >>> That can be done by object-detecting the proto-methods too, right? >> >> I'm not sure what you mean - how would you implement the functionality of >> Collator.resolveOptions without Collator objects? > > You wouldn't. I understood "fallbacks through object state" to mean testing > (typeof Globalization != "undefined" && Globalization.DateTimeFormat) or > equivalent, but testing for a prototype-based method can work as well. > > Clearly I misunderstood what "Find out if there were fallbacks through object > state" means. Could you give an example? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API discussion
Thanks for the clarification - this helps. I think however that the constructors of the Globalization API handle this correctly in most cases. The specs for the cases where the options object is not provided (sections /(8|9|10).2.(2|3)/), say the constructors behave as if they had received a minimal default, but that means they then also use all the other defaults. Effectively, they do: // handle missing options if (!ops) { ops = { foo: defFoo }; } // normal processing if (typeof ops.foo === "undefined") { foo = defFoo; } if (typeof ops.bar === "undefined") { bar = defBar; } if (typeof ops.baz === "undefined") { baz = defBaz; } That's a bit redundant, but generally produces the right results. Maybe breaking the constructor specifications into three subsections is just confusing, and I should merge them into one? There is a real problem, however, in the handling of date format components (10.2.1, and also the strawman for Date.prototype.toLocale(|Date|Time)String): The default for these components individually is undefined, meaning that the formatted string should only have the components that the caller requested. However, if the caller didn't request any components, then a default set should be filled in. With the current spec, the default set is only filled in if no options object is provided at all. If the caller, say, wants to request 24-hour time, it currently also has to specify the components. That's something I need to fix. The Globalization constructors don't modify the caller-provided options, by the way - I think that's a problem in your code. Thanks, Norbert On Nov 19, 2011, at 22:40 , David Herman wrote: > On Nov 19, 2011, at 5:50 PM, Brendan Eich wrote: > >> On Nov 19, 2011, at 2:20 PM, Rick Waldron wrote: >> >>> Q. We don't use option parameter like that in JS (see previous point for >>> actual example) >>> >>> Using an object-as-option parameter is a very common API design pattern in >>> real-world JavaScript today - why anyone would say otherwise is >>> confounding. >> >> Right. For example, ES5's property descriptor and property descriptor map >> parameters. > > It was me. I didn't say JS doesn't use options objects. I said the G11n > library was using them wrong. They were doing: > > if (!ops) { > ops = { foo: defFoo, bar: defBar, baz: defBaz }; > } > > instead of e.g.: > > if (!ops) > ops = {}; > if (typeof ops.foo === "undefined") > ops.foo = defFoo; > if (typeof ops.bar === "undefined") > ops.bar = defBar; > if (typeof ops.baz === "undefined") > ops.baz = defBaz; > > IOW, it shouldn't be all or nothing, but rather each property of the options > object is separately optional. > > Dave > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API discussion
On Nov 20, 2011, at 2:24 PM, Brendan Eich wrote: > On Nov 20, 2011, at 11:16 AM, Allen Wirfs-Brock wrote: > >> Actually, I think you would want to say: >> >> function frob(arg1, arg2, {foo = defFoo, bar = defBar, baz = defBaz}={}) { > > Thanks. > > >> It may be that for destructuring, in general, we want to treat a >> null/undefined RHS as { }. Eg: >> >> let {a=1,b=2,c=3} = undefined; >> //should this throw or should this be the same as: >> let {a=1,b=2,c=3} = { }; > > I would not add more implicit magic to JS. E4X had junk like this in it, > which only ever concealed bugs. I'm of two minds about this. In the abstract, I agree with Brendan; fail-soft conceals bugs. But in reality, our destructuring logic is incredible fail-soft. Hardly anything in destructuring is treated as an error. And the syntax really *wants* to match the common pattern. So I'm torn. Dave ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API discussion
On Nov 20, 2011, at 11:16 AM, Allen Wirfs-Brock wrote: > On Nov 20, 2011, at 10:03 AM, Brendan Eich wrote: > >> On Nov 20, 2011, at 8:12 AM, Rick Waldron wrote: >> >>> Ah, yes and agreed. That was definitely not relayed in the message below- >>> thanks for the clarification, the context does make a difference. >> >> Destructuring parameters + default values really shine here: >> >> function frob(arg1, arg2, {foo = defFoo, bar = defBar, baz = defBaz}) { >> // just use foo, bar, and baz instead of ops.foo, etc. >> } >> >> instead of the song and dance cited below. > > Actually, I think you would want to say: > > function frob(arg1, arg2, {foo = defFoo, bar = defBar, baz = defBaz}={}) { Thanks. > ... > } > > at least, according to how the ES6 draft is currently written. > Destructurings starts by applying ToObject to the value that is to be > destructured. ToObject throws for undefined and null. So, destructuring a > missing argument would throw. > > It may be that for destructuring, in general, we want to treat a > null/undefined RHS as { }. Eg: > > let {a=1,b=2,c=3} = undefined; > //should this throw or should this be the same as: > let {a=1,b=2,c=3} = { }; I would not add more implicit magic to JS. E4X had junk like this in it, which only ever concealed bugs. /be > > whichever way we go, we should treat all destructuring binding forms, > including formal parameters, consistently. > > Finally, whether or not you want to directly destructure an options object in > this matter probably depends upon its treatment of missing options. If a > missing option means something different from use the default value (such is > the case of property descriptors) then you wouldn't want to unconditionally > set missing property values to the default. > > Allen > > > > > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API discussion
On Nov 20, 2011, at 10:03 AM, Brendan Eich wrote: > On Nov 20, 2011, at 8:12 AM, Rick Waldron wrote: > >> Ah, yes and agreed. That was definitely not relayed in the message below- >> thanks for the clarification, the context does make a difference. > > Destructuring parameters + default values really shine here: > > function frob(arg1, arg2, {foo = defFoo, bar = defBar, baz = defBaz}) { > // just use foo, bar, and baz instead of ops.foo, etc. > } > > instead of the song and dance cited below. Actually, I think you would want to say: function frob(arg1, arg2, {foo = defFoo, bar = defBar, baz = defBaz}={}) { ... } at least, according to how the ES6 draft is currently written. Destructurings starts by applying ToObject to the value that is to be destructured. ToObject throws for undefined and null. So, destructuring a missing argument would throw. It may be that for destructuring, in general, we want to treat a null/undefined RHS as { }. Eg: let {a=1,b=2,c=3} = undefined; //should this throw or should this be the same as: let {a=1,b=2,c=3} = { }; whichever way we go, we should treat all destructuring binding forms, including formal parameters, consistently. Finally, whether or not you want to directly destructure an options object in this matter probably depends upon its treatment of missing options. If a missing option means something different from use the default value (such is the case of property descriptors) then you wouldn't want to unconditionally set missing property values to the default. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: modules, @std, selectively hiding/renaming imports
On Nov 20, 2011, at 2:04 AM, Claus Reinke wrote: > [btw: http://wiki.ecmascript.org/feed.php still gives me >url-encoded links; I thought that was meant to be > fixed by a wiki upgrade?] > > From the early drafts of a standard library > > http://wiki.ecmascript.org/doku.php?id=harmony:modules_standard > > it appears we are headed for an import name clash between > "Object.keys and "@iter.keys" - they cannot both be available as > plain "keys". Object is not a module, so there's no clash. Lots of methods named "keys" these days. Also the recent es-discuss thread on @iter suggests eliminating it in favor of @reflect, which we want for Proxy helpers too. > While the standard library needs a separate resolution, this > situation is not at all untypical for module-based development. > How are ES.next modules going to deal with this? We can locally > rename an imported id, but I see no facilities for import hiding > (import everything but a handful of ids), so how would we import > everything while renaming a few ids? We've mooted syntax for selective renaming, but import-all (import * from "...") lacks that feature in the current proposal. You'll have to be explicit in what you import. This ok. * imports are for prototyping, one-offs where you control both modules, and the like. They are not for everything. And anyway, there's non conflict with Object.keys. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
modules, @std, selectively hiding/renaming imports
[btw: http://wiki.ecmascript.org/feed.php still gives me url-encoded links; I thought that was meant to be fixed by a wiki upgrade?] From the early drafts of a standard library http://wiki.ecmascript.org/doku.php?id=harmony:modules_standard it appears we are headed for an import name clash between "Object.keys and "@iter.keys" - they cannot both be available as plain "keys". While the standard library needs a separate resolution, this situation is not at all untypical for module-based development. How are ES.next modules going to deal with this? We can locally rename an imported id, but I see no facilities for import hiding (import everything but a handful of ids), so how would we import everything while renaming a few ids? Claus http://clausreinke.github.com/ http://clausreinke.github.com/js-tools/ ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API discussion
On Nov 20, 2011, at 8:12 AM, Rick Waldron wrote: > Ah, yes and agreed. That was definitely not relayed in the message below- > thanks for the clarification, the context does make a difference. Destructuring parameters + default values really shine here: function frob(arg1, arg2, {foo = defFoo, bar = defBar, baz = defBaz}) { // just use foo, bar, and baz instead of ops.foo, etc. } instead of the song and dance cited below. /be > > Rick > > On Nov 20, 2011, at 1:40 AM, David Herman wrote: > >> On Nov 19, 2011, at 5:50 PM, Brendan Eich wrote: >> >>> On Nov 19, 2011, at 2:20 PM, Rick Waldron wrote: >>> Q. We don't use option parameter like that in JS (see previous point for actual example) Using an object-as-option parameter is a very common API design pattern in real-world JavaScript today - why anyone would say otherwise is confounding. >>> >>> Right. For example, ES5's property descriptor and property descriptor map >>> parameters. >> >> It was me. I didn't say JS doesn't use options objects. I said the G11n >> library was using them wrong. They were doing: >> >> if (!ops) { >> ops = { foo: defFoo, bar: defBar, baz: defBaz }; >> } >> >> instead of e.g.: >> >> if (!ops) >> ops = {}; >> if (typeof ops.foo === "undefined") >> ops.foo = defFoo; >> if (typeof ops.bar === "undefined") >> ops.bar = defBar; >> if (typeof ops.baz === "undefined") >> ops.baz = defBaz; >> >> IOW, it shouldn't be all or nothing, but rather each property of the options >> object is separately optional. >> >> Dave >> ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API: Objects needed?
On Nov 19, 2011, at 7:27 PM, Norbert Lindenberg wrote: >>> 2.a. Find out if there were fallbacks through object state >> >> That can be done by object-detecting the proto-methods too, right? > > I'm not sure what you mean - how would you implement the functionality of > Collator.resolveOptions without Collator objects? You wouldn't. I understood "fallbacks through object state" to mean testing (typeof Globalization != "undefined" && Globalization.DateTimeFormat) or equivalent, but testing for a prototype-based method can work as well. Clearly I misunderstood what "Find out if there were fallbacks through object state" means. Could you give an example? > >>> 2.b. Apply format repeatedly using the same options (internal caching may >>> remove this requirement) >> >> That seems like it could be a valid use-case in its own right, even with >> caching. Can you show code written both ways that makes realistic re-use of >> the object? > > The most common use case: > > var collator = new Globalization.Collator(localeList, options); > myArray.sort(function (x, y) { >return collator.compare(x, y); > }); > > This could also be written as: > > myArray.sort(function (x, y) { >return x.localeCompare(y, localeList, options); > }); > > but that would involve finding a cached Collator object for localeList and > options for every single string comparison, and sorting an array involves > many comparisons. > > But there are also applications that format large numbers of numbers or dates > in lists and tables, so that reusing an object would help. Thanks, that all makes sense. As Alex Russell pointed out, the DOM has default locale information induced by the browser and document. Making localeList an explicit parameter may just be burdening typical JS G11n code with having to acquire and then pass around the same information that (once control flows back into a DOM method that is *not* parameterized that way) is recovered from the default DOM information. If this is true, then it could be worth catering to the default locale(list). Hope I'm understanding this stuff -- corrections welcome. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Globalization API discussion
Ah, yes and agreed. That was definitely not relayed in the message below- thanks for the clarification, the context does make a difference. Rick On Nov 20, 2011, at 1:40 AM, David Herman wrote: > On Nov 19, 2011, at 5:50 PM, Brendan Eich wrote: > >> On Nov 19, 2011, at 2:20 PM, Rick Waldron wrote: >> >>> Q. We don't use option parameter like that in JS (see previous point for >>> actual example) >>> >>> Using an object-as-option parameter is a very common API design pattern in >>> real-world JavaScript today - why anyone would say otherwise is >>> confounding. >> >> Right. For example, ES5's property descriptor and property descriptor map >> parameters. > > It was me. I didn't say JS doesn't use options objects. I said the G11n > library was using them wrong. They were doing: > > if (!ops) { > ops = { foo: defFoo, bar: defBar, baz: defBaz }; > } > > instead of e.g.: > > if (!ops) > ops = {}; > if (typeof ops.foo === "undefined") > ops.foo = defFoo; > if (typeof ops.bar === "undefined") > ops.bar = defBar; > if (typeof ops.baz === "undefined") > ops.baz = defBaz; > > IOW, it shouldn't be all or nothing, but rather each property of the options > object is separately optional. > > Dave > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss