Default `this` value for static promise functions
Hi, I've just got bitten by return getError().then(Promise.reject); where `reject` threw an error that its `this` value was not a Promise constructor. Would it help to make the `C` constructor (in Promise.resolve, Promise.reject, Promise.all, Promise.race algorithms) default to `Promise` when no `this` value is supplied (throw only if it's there, but not an object and constructor function)? Or is this considered to be too error-prone with Promise subclassing, where `.then(MyCustomPromise.reject)` would not work as expected (fail silently)? regards, Bergi ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
On 7 April 2015 at 18:03, Nick Krempel ndkrem...@google.com wrote: On 6 April 2015 at 20:01, Jordan Harband ljh...@gmail.com wrote: If I want the short circuit in option 1, I'd do `a?.b?.c` to indicate that, whereas in option 2 if I don't want the short circuit, I'm forced to use separate variables. Worth noting that an option 1 `a?.b?.c` differs from an option 2 `a?.b.c` in that the latter is effectively asserting that if a != null then its b property is also != null, whereas the former is more lenient in what it accepts. Also you are not forced to use separate variables in option 2, you can just use parentheses: `(a?.b).c` - hence the whole discussion of lack of transitivity (more correctly, associativity) for option 2. Or did I misunderstand what you're trying to achieve? ...but thinking about it further, wouldn't you always want the short circuit semantics? i.e. an option 1 `a?.b.c` is almost certainly a bug? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
On 6 April 2015 at 20:01, Jordan Harband ljh...@gmail.com wrote: If I want the short circuit in option 1, I'd do `a?.b?.c` to indicate that, whereas in option 2 if I don't want the short circuit, I'm forced to use separate variables. Worth noting that an option 1 `a?.b?.c` differs from an option 2 `a?.b.c` in that the latter is effectively asserting that if a != null then its b property is also != null, whereas the former is more lenient in what it accepts. Also you are not forced to use separate variables in option 2, you can just use parentheses: `(a?.b).c` - hence the whole discussion of lack of transitivity (more correctly, associativity) for option 2. Or did I misunderstand what you're trying to achieve? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
On 6 April 2015 at 19:33, Christoph Pojer christoph.po...@gmail.com wrote: `a?.b` = `(a == null ? void 0 : a.b)` `a?.b.c` = `(a == null ? void 0 : a.b.c)` Would it not be more generally useful if it returned a rather than void 0 in the appropriate case, that is: `a?.b` = `(a == null ? a : a.b)` This way the notion of nullness/undefinedness the user is working with would be preserved. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Kevin Smith wrote: We should perhaps review this old thread: https://esdiscuss.org/topic/fail-fast-object-destructuring-don-t-add-more-slop-to-sloppy-mode for another possible way to avoid non-compositionality. (Look for the suggestion about Nil. It's basically an exotic falsey object which returns itself for any property lookups or calls.) Going a bit deeper this way, this thing (changing ref to Nil which always returns Nil upon call, construct and get, and getting back undefined when value is needed) have nicely separated concerns: Let's say '?foo', as an unary oper ator, when foo is a reference, returns Nil when foo is reference to null or undefined, otherwise leaves it unchanged. Then: ?a.b.c just works, ?d() just works, new ?e[i]() just works, etc,. since ref is changed to Nil if the thing is null/undefined, it propagates through calls and gets, then changes itself to undefined value. The priority of ? must be pretty high, though, to only apply to nearest token. Plus, it can be used for normalizing null/undefined to undefined: var normalizedFoo = ?foo; Seems sort of nice that it is separated and there are no special operations for ?., ?(, ?[. Herby ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
it doesn't have to be a bug. It asserts that if a is not null/undefined, it must have a property b. This can be enforced through static typing. On Tue, Apr 7, 2015 at 10:07 AM, Nick Krempel ndkrem...@google.com wrote: On 7 April 2015 at 18:03, Nick Krempel ndkrem...@google.com wrote: On 6 April 2015 at 20:01, Jordan Harband ljh...@gmail.com wrote: If I want the short circuit in option 1, I'd do `a?.b?.c` to indicate that, whereas in option 2 if I don't want the short circuit, I'm forced to use separate variables. Worth noting that an option 1 `a?.b?.c` differs from an option 2 `a?.b.c` in that the latter is effectively asserting that if a != null then its b property is also != null, whereas the former is more lenient in what it accepts. Also you are not forced to use separate variables in option 2, you can just use parentheses: `(a?.b).c` - hence the whole discussion of lack of transitivity (more correctly, associativity) for option 2. Or did I misunderstand what you're trying to achieve? ...but thinking about it further, wouldn't you always want the short circuit semantics? i.e. an option 1 `a?.b.c` is almost certainly a bug? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss -- Christoph Pojer http://cpojer.net ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Default `this` value for static promise functions
Or just throw: return getError().then(r = { throw r; }) -Original Message- From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Brendan Eich Sent: Tuesday, April 7, 2015 13:47 To: a.d.be...@web.de Cc: es-discuss@mozilla.org Subject: Re: Default `this` value for static promise functions a.d.be...@web.de wrote: Hi, I've just got bitten by return getError().then(Promise.reject); where `reject` threw an error that its `this` value was not a Promise constructor. Would it help to make the `C` constructor (in Promise.resolve, Promise.reject, Promise.all, Promise.race algorithms) default to `Promise` when no `this` value is supplied (throw only if it's there, but not an object and constructor function)? No, because as you suggested: Or is this considered to be too error-prone with Promise subclassing, where `.then(MyCustomPromise.reject)` would not work as expected (fail silently)? Probably the best solution is an arrow: return getError().then(r = Promise.reject(r)); /be ___ 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
Re: Existential Operator / Null Propagation Operator
Christoph Pojer wrote: it doesn't have to be a bug. It asserts that if a is not null/undefined, it must have a property b. This can be enforced through static typing. What do you mean? JS does not have static typing. Even if it got it via SoundScript, the new mode would be an opt-in. The default and vast majority of JS, which might like to use ?. (or whatever the syntax should be), could not rely on types. Kevin's suggestion is that we solve the non-compositional CoffeeScript-like translation problem by converting null-ish (null or undefined) left operand of ?. (I'll use that syntax for now as it is familiar) to the Nil (h/t bbenvie) value proxy, which soaks up further property accesses by returning itself, and soaks up calls too. As a sketch of semantics, this seems promising (no appeal to static typing) but I'm low on caffeine at the moment. What am I missing? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Array.prototype.find - Proposal for (breaking) change of API
I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.prototype.find - Proposal for (breaking) change of API
Then how could you find `undefined` in an array? That's a real use case too. In your A example, I'd represent that as: ``` var paths = files.map(file = path.resolve(base, file)); var found = paths.find(filePath = fs.existsSync(filePath)); ``` … and then `found` would be the resolved path you're looking for. On Tue, Apr 7, 2015 at 11:41 AM, Martin Heidegger martin.heideg...@gmail.com wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ 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
Re: Existential Operator / Null Propagation Operator
Christoph Pojer wrote: it doesn't have to be a bug. It asserts that if a is not null/undefined, it must have a property b. This can be enforced Oh, that is completely different semantics. IMNSHO, it goes against DWIM. through static typing. On Tue, Apr 7, 2015 at 10:07 AM, Nick Krempelndkrem...@google.com wrote: On 7 April 2015 at 18:03, Nick Krempelndkrem...@google.com wrote: On 6 April 2015 at 20:01, Jordan Harbandljh...@gmail.com wrote: If I want the short circuit in option 1, I'd do `a?.b?.c` to indicate that, whereas in option 2 if I don't want the short circuit, I'm forced to use separate variables. Worth noting that an option 1 `a?.b?.c` differs from an option 2 `a?.b.c` in that the latter is effectively asserting that if a != null then its b property is also != null, whereas the former is more lenient in what it accepts. Also you are not forced to use separate variables in option 2, you can just use parentheses: `(a?.b).c` - hence the whole discussion of lack of transitivity (more correctly, associativity) for option 2. Or did I misunderstand what you're trying to achieve? ...but thinking about it further, wouldn't you always want the short circuit semantics? i.e. an option 1 `a?.b.c` is almost certainly a bug? ___ 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
Re: Default `this` value for static promise functions
a.d.be...@web.de wrote: Hi, I've just got bitten by return getError().then(Promise.reject); where `reject` threw an error that its `this` value was not a Promise constructor. Would it help to make the `C` constructor (in Promise.resolve, Promise.reject, Promise.all, Promise.race algorithms) default to `Promise` when no `this` value is supplied (throw only if it's there, but not an object and constructor function)? No, because as you suggested: Or is this considered to be too error-prone with Promise subclassing, where `.then(MyCustomPromise.reject)` would not work as expected (fail silently)? Probably the best solution is an arrow: return getError().then(r = Promise.reject(r)); /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Kevin Smith wrote: Plus, it can be used for normalizing null/undefined to undefined: var normalizedFoo = ?foo; Seems sort of nice that it is separated and there are no special operations for ?., ?(, ?[. I agree, that is nice. But how does Nil get transformed into undefined? While you do operations like call, construct, get on the reference (obtaining another reference), it shortcuts to return Nil. Whenever you are not in position to shortcut ref-to-ref (end of expression, for example), and you actually needs a value, it just converts to undefined. ?a.b()['foo'] = smalltalk-like 'a' asRefIn: env) nilRefIfValueNullOrUndefined ref, may be nil at: 'b') returns ref, may be Nil callWithArguments: #()) returns ref, may be Nil at: 'foo') returns ref, may be Nil) value now, value is needed, ref needs to dereference Hopefully this sheds some light. If not, then I don't know how to explain it someone with better pedagogy skill must weight in. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Plus, it can be used for normalizing null/undefined to undefined: var normalizedFoo = ?foo; Seems sort of nice that it is separated and there are no special operations for ?., ?(, ?[. I agree, that is nice. But how does Nil get transformed into undefined? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Am I crazy to think that Nil could allow the Existential Operator to be used in assignments as well? var a = undefined; a?.b?.c?.d = 1; console.log(a); // {b: {c: {d: 1}}} Too powerful / abusive? Day dreaming, use U+02D9 (DOT ABOVE) as the operator. a˙b˙c.d On Tue, Apr 7, 2015 at 1:09 PM, Herby Vojčík he...@mailbox.sk wrote: Kevin Smith wrote: Plus, it can be used for normalizing null/undefined to undefined: var normalizedFoo = ?foo; Seems sort of nice that it is separated and there are no special operations for ?., ?(, ?[. I agree, that is nice. But how does Nil get transformed into undefined? While you do operations like call, construct, get on the reference (obtaining another reference), it shortcuts to return Nil. Whenever you are not in position to shortcut ref-to-ref (end of expression, for example), and you actually needs a value, it just converts to undefined. ?a.b()['foo'] = smalltalk-like 'a' asRefIn: env) nilRefIfValueNullOrUndefined ref, may be nil at: 'b') returns ref, may be Nil callWithArguments: #()) returns ref, may be Nil at: 'foo') returns ref, may be Nil) value now, value is needed, ref needs to dereference Hopefully this sheds some light. If not, then I don't know how to explain it someone with better pedagogy skill must weight in. ___ 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
Re: Array.prototype.find - Proposal for (breaking) change of API
You need lazy sequences aka iterators. They give you the rather optimal: let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); Libs like lodash and lazy.js provide the bits you need, which are actually fairly trivial to build on top of nice new ES6 iterators if you want. Alex On Tuesday, April 7, 2015, Martin Heidegger martin.heideg...@gmail.com wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ es-discuss mailing list es-discuss@mozilla.org javascript:; https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.prototype.find - Proposal for (breaking) change of API
not sure if off topic but * you need a with statement to use lodash like that * ... the following ... ``` let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); ``` is a very wasteful pattern ... have you ever heard of `some` ? ``` let found; some(files, _ = fs.existsSync(found = path.resolve(base, _)) || (found = '') || false); ``` It could bring few alchemies in ;-) On Tue, Apr 7, 2015 at 9:14 PM, Alexander Jones a...@weej.com wrote: You need lazy sequences aka iterators. They give you the rather optimal: let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); Libs like lodash and lazy.js provide the bits you need, which are actually fairly trivial to build on top of nice new ES6 iterators if you want. Alex On Tuesday, April 7, 2015, Martin Heidegger martin.heideg...@gmail.com wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ 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
RE: Array.prototype.find - Proposal for (breaking) change of API
Even more off-topic, I’m sure, but with http://github.com/rbuckton/queryjs (a query library over iterables) and ES6 you can do: ``` import { Query } from './query'; let files = [main.md, backup.md]; let base = /my/root; let found = Query .from(files) .map(file = path.resolve(base, file)) .filter(file = fs.existsSync(file)) .first(); ``` Ron From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Andrea Giammarchi Sent: Tuesday, April 7, 2015 1:40 PM To: Alexander Jones Cc: Martin Heidegger; es-discuss@mozilla.org Subject: Re: Array.prototype.find - Proposal for (breaking) change of API not sure if off topic but * you need a with statement to use lodash like that * ... the following ... ``` let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); ``` is a very wasteful pattern ... have you ever heard of `some` ? ``` let found; some(files, _ = fs.existsSync(found = path.resolve(base, _)) || (found = '') || false); ``` It could bring few alchemies in ;-) On Tue, Apr 7, 2015 at 9:14 PM, Alexander Jones a...@weej.commailto:a...@weej.com wrote: You need lazy sequences aka iterators. They give you the rather optimal: let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); Libs like lodash and lazy.js provide the bits you need, which are actually fairly trivial to build on top of nice new ES6 iterators if you want. Alex On Tuesday, April 7, 2015, Martin Heidegger martin.heideg...@gmail.commailto:martin.heideg...@gmail.com wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.mdhttp://main.md”, “backup.mdhttp://backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ es-discuss mailing list es-discuss@mozilla.orgmailto:es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.orgmailto: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
Re: Existential Operator / Null Propagation Operator
Nathan White wrote: Am I crazy to think that Nil could allow the Existential Operator to be used in assignments as well? var a = undefined; a?.b?.c?.d = 1; console.log(a); // {b: {c: {d: 1}}} Too powerful / abusive? Too error-prone. E4X (ECMA-357) and languages such as Borland's mid-nineties Lucy (Loose C) allow you to cons up deep structures just be expressing member references. One typo and you're lost. Day dreaming, use U+02D9 (DOT ABOVE) as the operator. a˙b˙c.d Object literal notation is explicit and pretty concise. What's the hot use-case driving your desire here? /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Existential Operator / Null Propagation Operator
On Mon, Apr 6, 2015 at 5:42 PM, Brendan Eich brendan at mozilla.org https://mail.mozilla.org/listinfo/es-discuss wrote: * Did you keep backward compatibility? `x?.1:y` must continue to work. * This is why I suggested a leading operator (`?a.?b()`) because it seems like it would have the least potential for conflict with existing valid syntax What about something like MemberExpression[?Yield] ? . IdentifierName MemberExpression[?Yield] ? *[* Expression[In, ?Yield] ] Context specific to MemberExpressions, as far as I'm aware there's no otherwise valid ternary expression that could be mixed up for it, and it wouldn't need a cover grammar? ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
March 24 2015 Meeting Notes
# March 24 2015 Meeting Notes Brian Terlson (BT), Allen Wirfs-Brock (AWB), John Neumann (JN), Jeff Morrison (JM), Sebastian Markbage (SM), Yehuda Katz (YK), Dave Herman (DH), Alan Schmitt (AS), Lee Byron (LB), Domenic Denicola (DD), Kevin Smith (KS), Andreas Rossberg (ARB), Brendan Eich (BE), Erik Arvidsson (EA), Adam Klein (AK), Jordan Harband (JHD), Mark Miller (MM), Istvan Sebestyen (IS), Jafar Husain (JH), Rick Waldron (RW) ## 4 ECMA-262 6th Edition (AWB) AWB: (presents slides) AWB: release candidates are intended to be complete subject to bugs so everyone could review them. RC1 was the review draft for the RF opt-out period. AWB: bug count fluctuates toward zero and back up; minor technical or editorial issues. Waldemar found some small issues in the grammar (unnecessary parametrization, Unicode regexp grammar, ...). Bugs that come up between now and June will be fixed as practical, or deferred to ES7 if not. AWB: any last minute issues!? BE: what about the things that are backward-incompatible? AWB: e.g. Brian has some issues around the function name property BT: i.e., the assignment of names when assigning a function to a var declaration AWB: EA has an issue around [[DefineOwnProperty]] on module namespace objects... BE: built-in prototypes? AWB: in RC1 it became pretty clear that at least making Array.prototype not-an-array would break at least some peoples' code. So for RC1 I reverted Array.prototype back to an Array exotic object. There was similar discussion about RegExp.prototype. For RC1 I did an experiment with some hacks that I thought would maybe give us a middle path. But that got reverted back. BE: not sure there's any profit in trying to change it in the spec. BT: that's what IE has: RegExp.prototype is an ordinary object; the only prototypes that are not ordinary objects are Function.prototype and Array.prototype. BE: what about `Object.prototype.toString` on those prototypes? [Actually I was asking what RegExp.prototype.toString() returns. /be] BT: it gives `[object Object]`. We haven't come across any code yet that breaks because of these changes, and to put that in perspective we have 3 or 4 sites that break due to the function name thing. ## Module Namespace Exotic Objects DH: I think there was a minor issue with the module namespace objects... EA: my concern here is that we're introducing a new exotic object. DH: that has been my intention for fully six years. (For some value of six.) DD: I think the wiki said `Object.create(null)` with getters... DH: yeah you're right, the exoticness is not the higher-order bit. AWB: let me run through the things you can do with a MNS exotic object. A get; no set; a get with a symbol; enumerate; has-own (name or symbol); and that's pretty much it. Everything else fails (false return or throw). So e.g. Object.getOwnPropertyDescriptor will throw on one of these. EA: a solution is to simply return a data property descriptor. Then code that uses Object.getOwnPropertyDescriptor, e.g. for mixins, will work. AWB: the reason I made it throw is that the MOP lets you define things that are neither data properties nor accessors, and this is one of those cases, and the MOP lets you throw in those cases, so we could. DH: it is self-evidently possible to write the spec as it's written now, but the question is whether we should. MM: I would find it more useful to not throw. AWB: even though it's not really writable? YK: it _is_ writable, but it's not writable by you. AWB: I worry that we're establishing a precedent that we're going to make [[GetOwnProperty]] behave that way. DH: there's a lot of code out there that has expectations about objects you give it, and if you build an object that breaks those expectations, then that particular class of object becomes rounded up and treated as toxic and people say to never use these objects, or alternately it starts to poison the well of these common operations, which is even worse. For example we did a similar thing with enumerate. Module objects ought to behave as close to normal objects as possible. It's a much narrower diversion to have an object which says it's writable but you can't write to it, than one that throws when you try to get a descriptor for its properties. On top of that, there is precedent for property writes quietly failing... MM: you could write something with an accessor that has that behavior, but it's not normal... non-writable properties normally throw in strict, fail silently in sloppy. AWB: being a data property means that if you get the descriptor you get the value of it. That means in [[GetOwnProperty]] I have to access the value, which could fail because of TDZ. DH: this is the MOP. TDZ is part of the core semantics. How do we reflect TDZ in the MOP. We could throw, or we could have some special representation of TDZ state in the MOP (e.g. undefined). A throw seems better at this stage, in
Re: March 26 2015 Meeting Notes
Erik Arvidsson wrote: (Brendan Eich presents https://gist.github.com/BrendanEich/4294d5c212a6d2254703) Moves to stage 1 was lost from end of line here. I'll have a github repo instead of a gist for this shortly. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Caitlin Potter wrote: 6, 2015 at 5:42 PM, Brendan Eichbrendan at mozilla.org https://mail.mozilla.org/listinfo/es-discuss wrote: / Did you keep backward compatibility? `x?.1:y` must continue to work. / This is why I suggested a leading operator (`?a.?b()`) because it seems like it would have the least potential for conflict with existing valid syntax What about something like MemberExpression[?Yield] ?|.| IdentifierName MemberExpression[?Yield] ?*[* Expression[In, ?Yield] |]| Context specific to MemberExpressions, as far as I'm aware there's no otherwise valid ternary expression that could be mixed up for it, and it wouldn't need a cover grammar? We can try being this precise, as you say -- but we cannot then handle x?(y) as CoffeeScript does. Instead of being neither fish nor fowl, better to be fowl with leading ?, or use a distinct and regular syntax that handles all the cases we want. My two cents, /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Brendan Eich wrote: Caitlin Potter wrote: 6, 2015 at 5:42 PM, Brendan Eichbrendan at mozilla.org https://mail.mozilla.org/listinfo/es-discuss wrote: / Did you keep backward compatibility? `x?.1:y` must continue to work. / This is why I suggested a leading operator (`?a.?b()`) because it seems like it would have the least potential for conflict with existing valid syntax What about something like MemberExpression[?Yield] ?|.| IdentifierName MemberExpression[?Yield] ?*[* Expression[In, ?Yield] |]| Context specific to MemberExpressions, as far as I'm aware there's no otherwise valid ternary expression that could be mixed up for it, and it wouldn't need a cover grammar? We can try being this precise, as you say -- but we cannot then handle x?(y) as CoffeeScript does. Instead of being neither fish nor fowl, better to be fowl with leading ?, or use a distinct and regular syntax that handles all the cases we want. My two cents, Worse, we can't even do ?[ as you propose with LR(1) or any similar approach. Here's a bison toy grammar: %token ID %% start: E ; E: A | E ',' A ; A: C | M '=' A ; C: M : M '?' A ':' A ; M: M '[' E ']' | M '?' '[' E ']' | P ; P: ID | '(' E ')' | '[' E ']' ; (P for Primary, M for Member, C for Conditional, A for Assignment.) The reduce/reduce conflict recognizing a left sentential form '[' E ']' vs. M '?' '[' E ']' shows the fatal ambiguity. /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
That's a good point. Are lexical non-DFA grammars allowed? It would be trivial to solve that with a regular expression lookahead. Although I suppose at that point you might as well call it a cover grammar. Joe On Mon, Apr 6, 2015 at 2:42 PM, Brendan Eich bren...@mozilla.org wrote: joe wrote: By the way, I don't remember having grammar issues (I use a LALR compiler-compiler). Looking at my code, it looked like I handled it in the tokenizer stage; I added a COND_DOT token: COND_DOT : \?\. Did you keep backward compatibility? `x?.1:y` must continue to work. /be No, it looks like I didn't. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.prototype.find - Proposal for (breaking) change of API
It's not wasteful if, as I said, they are iterator-consuming functions. I'm not sure why you think mutating a closed-over variable is better or more efficient code. Email me off list and I'll explain, or just look up the Python 3 map and filter (or Python 2 itertools equivalents). On Tuesday, April 7, 2015, Andrea Giammarchi andrea.giammar...@gmail.com wrote: not sure if off topic but * you need a with statement to use lodash like that * ... the following ... ``` let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); ``` is a very wasteful pattern ... have you ever heard of `some` ? ``` let found; some(files, _ = fs.existsSync(found = path.resolve(base, _)) || (found = '') || false); ``` It could bring few alchemies in ;-) On Tue, Apr 7, 2015 at 9:14 PM, Alexander Jones a...@weej.com javascript:_e(%7B%7D,'cvml','a...@weej.com'); wrote: You need lazy sequences aka iterators. They give you the rather optimal: let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); Libs like lodash and lazy.js provide the bits you need, which are actually fairly trivial to build on top of nice new ES6 iterators if you want. Alex On Tuesday, April 7, 2015, Martin Heidegger martin.heideg...@gmail.com javascript:_e(%7B%7D,'cvml','martin.heideg...@gmail.com'); wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org javascript:_e(%7B%7D,'cvml','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
Re: Array.prototype.find - Proposal for (breaking) change of API
actually never-mind, I got hooked by the Libs like lodash and lazy.js provide the bits you need and thought you were using those functions as if magically wrapped in a `with` statement ... oh well, sorry for the noise: keep iterating On Wed, Apr 8, 2015 at 12:28 AM, Andrea Giammarchi andrea.giammar...@gmail.com wrote: nope, I know it wasn't the bext example, but if you use Array methods as iterators examples I think I have a problem understanding what you are talking about. What you rote, in a JS Array world, is wasteful, and bad/non-optimal usage of Array patterns we have/know already. Maybe that's not the point you are trying to make, but surely mine, and when I read breaking change API and see non optimal patterns I believe the vision is not clear for everyone about where we are, and where we are moving. Apologies if that's not the reply you were hoping for On Wed, Apr 8, 2015 at 12:02 AM, Alexander Jones a...@weej.com wrote: It's not wasteful if, as I said, they are iterator-consuming functions. I'm not sure why you think mutating a closed-over variable is better or more efficient code. Email me off list and I'll explain, or just look up the Python 3 map and filter (or Python 2 itertools equivalents). On Tuesday, April 7, 2015, Andrea Giammarchi andrea.giammar...@gmail.com wrote: not sure if off topic but * you need a with statement to use lodash like that * ... the following ... ``` let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); ``` is a very wasteful pattern ... have you ever heard of `some` ? ``` let found; some(files, _ = fs.existsSync(found = path.resolve(base, _)) || (found = '') || false); ``` It could bring few alchemies in ;-) On Tue, Apr 7, 2015 at 9:14 PM, Alexander Jones a...@weej.com wrote: You need lazy sequences aka iterators. They give you the rather optimal: let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); Libs like lodash and lazy.js provide the bits you need, which are actually fairly trivial to build on top of nice new ES6 iterators if you want. Alex On Tuesday, April 7, 2015, Martin Heidegger martin.heideg...@gmail.com wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ 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
RE: Existential Operator / Null Propagation Operator
Brendan Eich wrote: Brendan Eich wrote: Caitlin Potter wrote: 6, 2015 at 5:42 PM, Brendan Eichbrendan at mozilla.org https://mail.mozilla.org/listinfo/es-discuss wrote: / Did you keep backward compatibility? `x?.1:y` must continue to work. / This is why I suggested a leading operator (`?a.?b()`) because it seems like it would have the least potential for conflict with existing valid syntax What about something like MemberExpression[?Yield] ?|.| IdentifierName MemberExpression[?Yield] ?*[* Expression[In, ?Yield] |]| Context specific to MemberExpressions, as far as I'm aware there's no otherwise valid ternary expression that could be mixed up for it, and it wouldn't need a cover grammar? We can try being this precise, as you say -- but we cannot then handle x?(y) as CoffeeScript does. Instead of being neither fish nor fowl, better to be fowl with leading ?, or use a distinct and regular syntax that handles all the cases we want. My two cents, The reduce/reduce conflict recognizing a left sentential form '[' E ']' vs. M '?' '[' E ']' shows the fatal ambiguity. /be There is also ambiguity due to ASI vs. a ConditionalExpression: ``` obj ? [ expr ] :label ``` Ron ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Array.prototype.find - Proposal for (breaking) change of API
nope, I know it wasn't the bext example, but if you use Array methods as iterators examples I think I have a problem understanding what you are talking about. What you rote, in a JS Array world, is wasteful, and bad/non-optimal usage of Array patterns we have/know already. Maybe that's not the point you are trying to make, but surely mine, and when I read breaking change API and see non optimal patterns I believe the vision is not clear for everyone about where we are, and where we are moving. Apologies if that's not the reply you were hoping for On Wed, Apr 8, 2015 at 12:02 AM, Alexander Jones a...@weej.com wrote: It's not wasteful if, as I said, they are iterator-consuming functions. I'm not sure why you think mutating a closed-over variable is better or more efficient code. Email me off list and I'll explain, or just look up the Python 3 map and filter (or Python 2 itertools equivalents). On Tuesday, April 7, 2015, Andrea Giammarchi andrea.giammar...@gmail.com wrote: not sure if off topic but * you need a with statement to use lodash like that * ... the following ... ``` let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); ``` is a very wasteful pattern ... have you ever heard of `some` ? ``` let found; some(files, _ = fs.existsSync(found = path.resolve(base, _)) || (found = '') || false); ``` It could bring few alchemies in ;-) On Tue, Apr 7, 2015 at 9:14 PM, Alexander Jones a...@weej.com wrote: You need lazy sequences aka iterators. They give you the rather optimal: let found = first(filter( map(files, _ = path.resolve(base, _)), fs.existsSync )); Libs like lodash and lazy.js provide the bits you need, which are actually fairly trivial to build on top of nice new ES6 iterators if you want. Alex On Tuesday, April 7, 2015, Martin Heidegger martin.heideg...@gmail.com wrote: I am probably very late to the game but I just read about harmonies “Array.prototype.find” and found that it might be worth considering a change in way it works. Its not a drastic change but it would break the compatibility to the current setup. I understand that the chances for this going through will be slim but since I would like to give it a shot anyways: Currently the API uses a callback function that has to return a boolean to identify the item that has been found. This is good because find findIndex can use the same methods but it also has a drawback. Problem: Say you have a list of items that need to be processed before you know if you “found” the item. Then you will need to process the last item again since there is no way to “keep” the result (A) of the find method or you preprocess all items using map (B) that will require to process all the items even if the first one already matches. Example: (BASE) var files = [“main.md”, “backup.md”] var base = “/my/root (A) // Specifies `path.resolve` on two places var found = files.find(function (file) { return fs.existsSync(path.resolve(base, file)) })) if (found) found = path.resolve(base, file) (B) // Runs `path.resolve` for all items var found = files.map(function (file) { return path.resolve(base, file) }).find(fs.existsSync) Proposal (C): I think it might be interesting to have a change of the signature so that the return value is not true/false but the value that actually will be returned (not undefined): (C) var found = files.find(function (file) { file = path.resolve(base, file) if(fs.existsSync(file)) return file }); This way the operations would be minimised, it is still few to write and it would make life a bit easier. yours Martin Heidegger ___ 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
Re: Existential Operator / Null Propagation Operator
Ron Buckton wrote: The reduce/reduce conflict recognizing a left sentential form '[' E ']' vs. M '?' '[' E ']' shows the fatal ambiguity. /be There is also ambiguity due to ASI vs. a ConditionalExpression: ``` obj ? [ expr ] :label ``` Ron Colon goes after label :-P. But the problem is bounded lookahead, ideally k=1. We are not specifying backtracking... /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
joe wrote: That's a good point. Are lexical non-DFA grammars allowed? It would be trivial to solve that with a regular expression lookahead. Although I suppose at that point you might as well call it a cover grammar. We must avoid being too clever -- it complicates implementations and inevitably incurs future-hostility to extensions we may want, if not outright bugginess. All of this suggests prefix ? is the better course. Anyone have counterexamples? /be Joe On Mon, Apr 6, 2015 at 2:42 PM, Brendan Eich bren...@mozilla.org mailto:bren...@mozilla.org wrote: joe wrote: By the way, I don't remember having grammar issues (I use a LALR compiler-compiler). Looking at my code, it looked like I handled it in the tokenizer stage; I added a COND_DOT token: COND_DOT : \?\. Did you keep backward compatibility? `x?.1:y` must continue to work. /be No, it looks like I didn't. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
RE: Existential Operator / Null Propagation Operator
Oops, was think in batch for a minute there. Sent from my Windows Phone From: Brendan Eichmailto:bren...@mozilla.org Sent: 4/7/2015 6:23 PM To: Ron Bucktonmailto:ron.buck...@microsoft.com Cc: Caitlin Pottermailto:caitpotte...@gmail.com; es-discuss@mozilla.orgmailto:es-discuss@mozilla.org Subject: Re: Existential Operator / Null Propagation Operator Ron Buckton wrote: The reduce/reduce conflict recognizing a left sentential form '[' E ']' vs. M '?' '[' E ']' shows the fatal ambiguity. /be There is also ambiguity due to ASI vs. a ConditionalExpression: ``` obj ? [ expr ] :label ``` Ron Colon goes after label :-P. But the problem is bounded lookahead, ideally k=1. We are not specifying backtracking... /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
Okay. I've updated my transpiler to demonstrate how (and why) this could work at the VM level (I do think VM devs will have to add new opcodes for this), and I've appended an example transformation to this email. Why is this so complicationed? The answer is that when you start nesting ?. operators, it's pretty easy to cause some operators to be called twice. E.g, if you transformed the following to the NULL syntax: a?.d().f?.b You would get: (a != undefined ? (a.d() != undefined ? (a.d().f != undefined ? a.d().f.b : undefined) : undefined))); Notice how a.d() gets called multiple times. The solution is probably new VM opcodes. Since my transpiler is obviously not a VM, it transforms ?. operators into auto-generated functions. Anyway, here's the example I transpiler: a?.b.c.e?.f.g?.h.t.c?.d()?.e; Which turned into this: function q0eILlfx7_3(obj) { var _t=obj; if (_t==undefined) return undefined; _t = _t.b.c.e; if (_t==undefined) return undefined; _t = _t.f.g; if (_t==undefined) return undefined; _t = _t.h.t.c; if (_t==undefined) return undefined; _t = _t.d(); return _t; } q0eILlfx7_3(a); On Tue, Apr 7, 2015 at 6:24 PM, Brendan Eich bren...@mozilla.org wrote: joe wrote: That's a good point. Are lexical non-DFA grammars allowed? It would be trivial to solve that with a regular expression lookahead. Although I suppose at that point you might as well call it a cover grammar. We must avoid being too clever -- it complicates implementations and inevitably incurs future-hostility to extensions we may want, if not outright bugginess. All of this suggests prefix ? is the better course. Anyone have counterexamples? /be Joe On Mon, Apr 6, 2015 at 2:42 PM, Brendan Eich bren...@mozilla.org mailto:bren...@mozilla.org wrote: joe wrote: By the way, I don't remember having grammar issues (I use a LALR compiler-compiler). Looking at my code, it looked like I handled it in the tokenizer stage; I added a COND_DOT token: COND_DOT : \?\. Did you keep backward compatibility? `x?.1:y` must continue to work. /be No, it looks like I didn't. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
No, you’d just memoise it to a variable: a?.d().f?.b to: var _temp, _temp2; (a != undefined ? (temp = a.d() != undefined ? (_temp2 = _temp.f != undefined ? _temp2.b : undefined) : undefined))); You’re going to need to memoise all member expressions anyway as they might be accessing a getter and you don’t want to call it twice. On Tue, Apr 7, 2015 at 7:32 PM, joe joe...@gmail.com wrote: Okay. I've updated my transpiler to demonstrate how (and why) this could work at the VM level (I do think VM devs will have to add new opcodes for this), and I've appended an example transformation to this email. Why is this so complicationed? The answer is that when you start nesting ?. operators, it's pretty easy to cause some operators to be called twice. E.g, if you transformed the following to the NULL syntax: a?.d().f?.b You would get: (a != undefined ? (a.d() != undefined ? (a.d().f != undefined ? a.d().f.b : undefined) : undefined))); Notice how a.d() gets called multiple times. The solution is probably new VM opcodes. Since my transpiler is obviously not a VM, it transforms ?. operators into auto-generated functions. Anyway, here's the example I transpiler: a?.b.c.e?.f.g?.h.t.c?.d()?.e; Which turned into this: function q0eILlfx7_3(obj) { var _t=obj; if (_t==undefined) return undefined; _t = _t.b.c.e; if (_t==undefined) return undefined; _t = _t.f.g; if (_t==undefined) return undefined; _t = _t.h.t.c; if (_t==undefined) return undefined; _t = _t.d(); return _t; } q0eILlfx7_3(a); On Tue, Apr 7, 2015 at 6:24 PM, Brendan Eich bren...@mozilla.org wrote: joe wrote: That's a good point. Are lexical non-DFA grammars allowed? It would be trivial to solve that with a regular expression lookahead. Although I suppose at that point you might as well call it a cover grammar. We must avoid being too clever -- it complicates implementations and inevitably incurs future-hostility to extensions we may want, if not outright bugginess. All of this suggests prefix ? is the better course. Anyone have counterexamples? /be Joe On Mon, Apr 6, 2015 at 2:42 PM, Brendan Eich bren...@mozilla.org mailto:bren...@mozilla.org wrote: joe wrote: By the way, I don't remember having grammar issues (I use a LALR compiler-compiler). Looking at my code, it looked like I handled it in the tokenizer stage; I added a COND_DOT token: COND_DOT : \?\. Did you keep backward compatibility? `x?.1:y` must continue to work. /be No, it looks like I didn't. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Existential Operator / Null Propagation Operator
That looks workable. Does anyone have any more comments on '.?' versus '?.' ? Joe On Tue, Apr 7, 2015 at 7:34 PM, Sebastian McKenzie seb...@gmail.com wrote: No, you’d just memoise it to a variable: a?.d().f?.b to: var _temp, _temp2; (a != undefined ? (temp = a.d() != undefined ? (_temp2 = _temp.f != undefined ? _temp2.b : undefined) : undefined))); You’re going to need to memoise all member expressions anyway as they might be accessing a getter and you don’t want to call it twice. On Tue, Apr 7, 2015 at 7:32 PM, joe joe...@gmail.com wrote: Okay. I've updated my transpiler to demonstrate how (and why) this could work at the VM level (I do think VM devs will have to add new opcodes for this), and I've appended an example transformation to this email. Why is this so complicationed? The answer is that when you start nesting ?. operators, it's pretty easy to cause some operators to be called twice. E.g, if you transformed the following to the NULL syntax: a?.d().f?.b You would get: (a != undefined ? (a.d() != undefined ? (a.d().f != undefined ? a.d().f.b : undefined) : undefined))); Notice how a.d() gets called multiple times. The solution is probably new VM opcodes. Since my transpiler is obviously not a VM, it transforms ?. operators into auto-generated functions. Anyway, here's the example I transpiler: a?.b.c.e?.f.g?.h.t.c?.d()?.e; Which turned into this: function q0eILlfx7_3(obj) { var _t=obj; if (_t==undefined) return undefined; _t = _t.b.c.e; if (_t==undefined) return undefined; _t = _t.f.g; if (_t==undefined) return undefined; _t = _t.h.t.c; if (_t==undefined) return undefined; _t = _t.d(); return _t; } q0eILlfx7_3(a); On Tue, Apr 7, 2015 at 6:24 PM, Brendan Eich bren...@mozilla.org wrote: joe wrote: That's a good point. Are lexical non-DFA grammars allowed? It would be trivial to solve that with a regular expression lookahead. Although I suppose at that point you might as well call it a cover grammar. We must avoid being too clever -- it complicates implementations and inevitably incurs future-hostility to extensions we may want, if not outright bugginess. All of this suggests prefix ? is the better course. Anyone have counterexamples? /be Joe On Mon, Apr 6, 2015 at 2:42 PM, Brendan Eich bren...@mozilla.org mailto:bren...@mozilla.org wrote: joe wrote: By the way, I don't remember having grammar issues (I use a LALR compiler-compiler). Looking at my code, it looked like I handled it in the tokenizer stage; I added a COND_DOT token: COND_DOT : \?\. Did you keep backward compatibility? `x?.1:y` must continue to work. /be No, it looks like I didn't. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss