Re: Since JSDoc seems cerebrally dead...
This SO answer provides a typing for Object.assign that appears to basically do the right thing: https://stackoverflow.com/a/51603499 -- but none of the above libraries use this kind of solution, which leads me to think it might not be totally robust On Wed, Nov 11, 2020 at 1:27 PM Jordan Harband wrote: > Of course there's a way - it's just that TS's built-in types don't > consistently go the extra mile, and often resort to `any`. See > https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5344bfc80508c53a23dae37b860fb0c905ff7b24/types/object-assign/index.d.ts, > or > https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/lodash/common/object.d.ts#L32-L52, > for two examples of `Object.assign`, as an example. > > On Wed, Nov 11, 2020 at 8:51 AM Michaël Rouges > wrote: > >> Some other cases, not covered, even in JSDoc nor TS >> >> There is no way to describe the result, to the IDE's intellisense, for >> those ES5/ES2015 features: >> `Object.create(prototype, descriptors)` >> https://github.com/microsoft/TypeScript/blob/master/lib/lib.es5.d.ts#L192 >> `Object.assign(obj, ...mixins)` >> https://github.com/microsoft/TypeScript/blob/master/lib/lib.es2015.core.d.ts#L313 >> >> I really love JS, but if there is no way to help the IDE to understand >> complex things, it's like to code with a Notepad.exe >> >> Any TC feelings about that, please? >> >> Michaël Rouges - https://github.com/Lcfvs - @Lcfvs >> >> >> Le dim. 18 oct. 2020 à 05:27, #!/JoePea a écrit : >> >>> That would be interesting indeed. Encouraging documentation is great I >>> think. >>> #!/JoePea >>> >>> On Sat, Oct 17, 2020 at 3:38 AM Michaël Rouges >>> wrote: >>> > >>> > Yeah, I prefer the JSDoc solution too for the same reasons... but >>> JSDoc is really slow to evolve, >>> > always several years behind the standard, a lot of solutions to >>> describe our code are more relevant >>> > to **tricks**, generally found on the JSDoc issues, than something >>> formal. >>> > >>> > The coverage isn't the same... really, I'm dreaming about a standard >>> annotation for each ES feature, >>> > covering all the usages. **when that feature is released**. >>> > >>> > >>> > Michaël Rouges - https://github.com/Lcfvs - @Lcfvs >>> > >>> > >>> > Le sam. 17 oct. 2020 à 03:29, #!/JoePea a écrit : >>> >> >>> >> Would official syntax be worth it (JSDoc being officially >>> standardized)? >>> >> >>> >> Maybe it's a matter of time: Perhaps now that JSDoc is useful for type >>> >> checking (thanks to TypeScript and its ability to type check plain >>> >> JavaScript that is annotated with JSDoc) it may be closer to reality. >>> >> >>> >> I prefer JSDoc type annotation in plain .js files over writing .ts >>> >> files, because it means I can write type-checked code that has great >>> >> intellisense in modern editors like VS Code, without needing any build >>> >> steps and with end users being able to consume those source files >>> >> directly in any way they want (possibly also without build tools). >>> >> However, JSDoc can not currently do everything that regular TypeScript >>> >> syntax can do (there's some open issues regarding that in the >>> >> TypeScript repo). >>> >> >>> >> #!/JoePea >>> >> >>> >> On Wed, Oct 14, 2020 at 11:53 AM kai zhu wrote: >>> >> > >>> >> > > Sorry but my question isn't about providing a tool to generate >>> our documentations but to have a standard syntax to describe our code >>> (signatures). ;) >>> >> > >>> >> > not standard-practice, but my style is to have documentation of >>> functions inside the function (rather than above it). >>> >> > simplifies doc-generation by calling function's `.toString()` >>> (rather than having to parse the parse the entire script): >>> >> > >>> >> > ```js >>> >> > let html; >>> >> > let local; >>> >> > local = {}; >>> >> > local.foo1 = function (aa, bb) { >>> >> > /* >>> >> > * this function will blah blah blah >>> >> > */ >>> >> > return aa + bb; >>> >> > }; >>> >> > local.foo2 = function (cc, dd) { >>> >> > /* >>> >> > * this function will yada yada yada >>> >> > */ >>> >> > return cc + dd; >>> >> > }; >>> >> > >>> >> > // auto-generate doc for functions in namespace >>> >> > html = "\n\n"; >>> >> > Object.entries(local).sort().forEach(function ([ >>> >> > name, obj >>> >> > ]) { >>> >> > if (typeof obj === "function") { >>> >> > obj.toString().replace(( >>> >> > >>> /function\b.*?(\([\S\s]*?\))\s*?\{\n?(\s*?\/\*[\S\s]*?\*\/)/ >>> >> > ), function (ignore, signature, comment) { >>> >> > html += "function " + name + " " + signature.trim() >>> + "\n"; >>> >> > html += "\n" + comment + "\n\n"; >>> >> > html += "\n"; >>> >> > }); >>> >> > } >>> >> > }); >>> >> > html += "\n"; >>> >> > console.log(html); >>> >> > ``` >>> >> > >>> >> > output >>> >> > ```html >>> >> > >>> >> > >>> >> > function foo1 (aa, bb) >>> >> > >>> >> > /* >>> >> > * this function will blah blah blah >>> >> > */ >>> >> > >>> >> >
Re: Default values for nulls
I'd find it more readable to allow an assignment operator, with the semantic "do this transformation, using the passed value as the previous value" ``` function (x ??= 123) {} // If passed null or undefined, x = 123 function (x &&= 123) {} // If passed a truthy value, x = 123 function (x += 123) {} // Regardless of type, add 123 to x ``` That said, I can see how allowing the arithmetic-assignment (and concat-assignment) operators could lead hard-to-debug code that uses some "I am very smart" shortcuts, so I'd opt to start with the logical-assignment operators On Tue, Oct 13, 2020 at 9:08 AM Naveen Chawla wrote: > What about allowing any expression then? > > x || 4 > x/4 > x + 4 > x + w //maybe allow only "previous" parameter values as scope > x + a //SyntaxError: 'a' undefined in parameters scope > > On Tue, 13 Oct 2020 at 14:39, Michael Luder-Rosefield < > rosyatran...@gmail.com> wrote: > >> I know I am not the only one who has had several perfectly good use-cases >> for default values disallowed, because the value coming in was `null`, not >> `undefined`. >> >> I cannot be the only one who has let bugs slip in because of failing to >> consider this case. >> >> So, if we can find a non-confusing and simple way to alter the spec to >> allow for handling this, I imagine it would be considered useful and wanted. >> >> The obvious candidate is the nullish coalescing operator, which is >> already part of the spec. Unfortunately, it is currently invalid to >> indicate default values with it. I can't see any reason against changing >> this. >> >> ``` >> function foo1 (x = 4) { >> console.log(x); >> } >> >> // currently causes SyntaxError >> function foo2 (x ?? 4) { >> console.log(x); >> } >> >> foo1(null); // null >> foo1(undefined) // 4 >> >> foo2(null); // 4 >> foo2(undefined) // 4 >> >> // currently causes SyntaxError >> // should give x === null, y === 4 >> const { x = 2, y ?? 4 } = { x: null, y: null }; >> ``` >> -- >> Dammit babies, you've got to be kind. >> ___ >> 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: Re: Flags enums
For what it's worth, TypeScript has Enums built-in and I find myself using string literal types instead: ```typescript type CollisionType = 'CIRCLE' | 'CUBIC_BEZIER_CURVE' | 'RIGID_BODY'; function handleCollision(type: CollisionType) { if (type === 'CIRCLE') { // ... } else if (type === 'SQUARE') { // Tooling errors on this line // ... } } ``` In VSCode (and I assume other IDEs that support TypeScript) you can even do this in vanilla JS with structured JSDoc comments and the tooling will type check for you: ```javascript // @ts-check /** @typedef {'CIRCLE' | 'CUBIC_BEZIER_CURVE' | 'RIGID_BODY'} CollisionType */ /** * @param {CollisionType} type */ function handleCollision(type) { if (type === 'CIRCLE') { // ... } else if (type === 'SQUARE') { // Tooling errors on this line // ... } } ``` As far as I know, comparing strings is nearly as performant in most JS engines as comparing numbers or objects because they use a method called "string interning" On Wed, Aug 26, 2020 at 2:25 PM Matheus Dias de Souza wrote: > > > The com.siteblade.util package contains an approximation of this in > ECMAScript, with no difference, except the valueOf() method (which returns > String for working with equality), so it ends up with an additional getter > ‘number’. > > > > https://www.npmjs.com/package/com.siteblade.util > > > > You can use either FlagsEnum or Enum. > > > > import { Enum } from 'com.siteblade.util'; > > > > const CollisionType = Enum('CollisionType', [ > > ['CIRCLE'], > > ['CUBIC_BEZIER_CURVE', [10]], > > ['RIGID_BODY', ['rigidBody', 2]] > > ]); > > > > var type = CollisionType('cubicBezierCurve'); > > console.log( type == 'cubicBezierCurve' ); > ___ > 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: Since JSDoc seems cerebrally dead...
> This feels like rich territory for a blog post, if someone feels qualified? Specifically, just running the typescript tool chain for jsdoc annotations, which are excellent for all the reasons mentioned above (comments only, vanilla js etc). Does this count? https://devblogs.microsoft.com/typescript/how-to-upgrade-to-typescript-without-anybody-noticing-part-1/ On Mon, Aug 17, 2020 at 2:56 PM Dan Peddle wrote: > This feels like rich territory for a blog post, if someone feels > qualified? Specifically, just running the typescript tool chain for jsdoc > annotations, which are excellent for all the reasons mentioned above > (comments only, vanilla js etc). > > On 17. Aug 2020, at 19:35, Andrea Giammarchi > wrote: > > > Sorry, new link: > https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html > > On Mon, Aug 17, 2020 at 8:34 PM Andrea Giammarchi < > andrea.giammar...@gmail.com> wrote: > >> TS supports JSDocs already >> >> https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html#supported-jsdoc >> >> On Mon, Aug 17, 2020 at 8:31 PM Bergi wrote: >> >>> Hi, >>> >>> > They don't want to add TS to their stack. >>> >>> Then what else would they want to add to their stack? Notice one doesn't >>> necessarily need the TypeScript Compiler to add TypeScript- or Flow-like >>> type annotations and remove them in a build step - Babel for example >>> could do that just fine as well. >>> Or are you asking for a jsdoc-like thing that lives in comments, where >>> the code can be run without a compilation step? >>> >>> kind regards, >>> Bergi >>> ___ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Any way to detect an async stack trace (like Chrome devtools does)?
Reading through the issue JoePea linked to, it looks like the difficulties with standardized async stack traces are twofold: 1. Even with the error stacks proposal, the implementer has total say over what qualifies as a stack frame 2. The way promises are chained means that some patterns like async loops would theoretically unroll to very long stack traces, and right now engines aren't required to keep track of those frames; requiring them to do so would place a burden on implementers that could quickly lead to slowdowns and memory issues What if there was a standard way to mark a Promise as an important stack frame, which the implementer is free to ignore? Maybe something like `Promise.prototype.trace()` On Fri, Jul 10, 2020 at 10:22 PM #!/JoePea wrote: > Hello Kai! That example is so meta with its own output showing the > numbers relative to the code including its own output! :) > > That's what I originally wanted to do, but that doesn't give us an > async stack trace, it only gives a sync stack trace (I presume within > the current event loop task). > > For example: > > ```js > const originalFetch = globalThis.fetch > > globalThis.fetch = function(...args) { > const stack = new Error().stack > console.log(stack) > return originalFetch.apply(globalThis, args) > } > > const sleep = t => new Promise(r => setTimeout(r, t)) > > async function one() { > console.log('1') > await sleep(10) > two() > } > > async function two() { > console.log('2') > await sleep(10) > three() > } > > async function three() { > console.log('3') > await sleep(10) > return await fetch('https://unpkg.com/three@0.118.3') > } > > async function main() { > await one() > } > > main() > ``` > > Output: > > ``` > 1 > 2 > 3 > Error > at globalThis.fetch (pen.js:5) > at three (pen.js:27) > ``` > > Live example: > > > https://codepen.io/trusktr/pen/b8fd92752b4671268f516ad3804869e4?editors=1010 > > I opened a request for this over here: > https://github.com/tc39/proposal-error-stacks/issues/34 > > #!/JoePea > > On Fri, Jul 10, 2020 at 1:21 PM kai zhu wrote: > > > > > (I want to detect traces in third-party code installed locally). > > > > 1. here's 15-line javascript-hack to trace async-fetch-calls from > 3rd-party-cdn-library > > > > ```html > > > > > > > > test.html > > > > (function () { > > /* > > * 15-line-javascript-hack to trace async-fetch-calls > > * enable hack by adding search-query "?modeDebugFetch=1" to web-url > > */ > > "use strict"; > > if ((/\bmodeDebugFetch=1\b/).test(location.search)) { > > let fetch0; > > fetch0 = globalThis.fetch; > > globalThis.fetch = function (...argList) { > > let errStack = new Error().stack; > > console.error("\n\nfetch-call-arguments:"); > > console.error(JSON.stringify(argList, undefined, 4)); > > console.error("\n\nfetch-call-trace:"); > > console.error(errStack); > > return fetch0(...argList); > > }; > > } > > }()); > > > > > > https://unpkg.com/http-client/umd/http-client.js"> > > > > (async function foo() { > > "use strict"; > > let thirdParty = window.HTTPClient; > > let myFetch = thirdParty.createFetch( > > thirdParty.base("https://api.stripe.com/v1"), > > thirdParty.accept("application/json") > > ); > > let response = await myFetch("/customers/5"); > > console.log(response.jsonData); > > /* > > dev-console-output - http://localhost:8081/test.html?modeDebugFetch=1 > > fetch-call-arguments: > > [ > > "https://api.stripe.com/v1/customers/5", > > { > > "headers": { > > "Accept": "application/json" > > }, > > "responseHandlers": [ > > null > > ] > > } > > ] > > fetch-call-trace: > > Error > > at globalThis.fetch (test.html?modeDebugFetch=1:16) > > at http-client.js:194 > > at http-client.js:127 > > at http-client.js:217 > > at http-client.js:126 > > at http-client.js:154 > > at http-client.js:95 > > at foo (test.html?modeDebugFetch=1:35) > > at test.html?modeDebugFetch=1:64 > > */ > > }()); > > > > > > ``` > > > > > > 2. here's real-world-hack added to npm-cli.js to debug its http-requests > > > > ```diff > > C:\Program Files\nodejs\node_modules\npm>git diff > > diff --git a/bin/npm-cli.js b/bin/npm-cli.js > > index 561dec0..98cafb8 100644 > > --- a/bin/npm-cli.js > > +++ b/bin/npm-cli.js > > @@ -2,17 +2,6 @@ > > ;(function () { // wrapper in case we're in module_context mode > > +// hack - debug http-request > > +let httpRequest; > > +httpRequest = require("https").request.bind(require("https")); > > +require("https").request = function (...argList) { > > +
Re: Proposal: Forced Chaining Operator "!."
(Sorry for the triple-post, I keep pondering this proposal) Come to think of it, you could do something pretty similar with the `??=` operator from the logical assignments proposal: ```javascript (((table ??= {}).user ??= {}).id ??= {}).type = 'int'; ``` The main difference being that it tests for nullishness instead of whether the LHS is a non-null object, but I think that's within the spirit of the original proposal. It also lets you set a custom default value (like the "getsert" function above). The shortfall of course is the accumulating parentheses On Sat, Apr 25, 2020 at 8:08 PM Jacob Bloom wrote: > Is the Perl syntax opt-in like the proposed operator? Or does it happen on > all accesses to nulls? If it's opt-in in JS, then it doesn't seem to me > that it'd cause too much unexpected behavior, though it could be argued > that it's ripe for abuse by new devs trying to avoid errors. > > Something that might be a more generalized middle ground (and could later > assist in transpiling the !. operator) is a "getsert" (?) method in the > standard library that takes a default value and sets it on the parent > object if that property is currently unset: > > ```javascript > Object.getsert = (obj, identifier, defaultvalue) => { > if (!(identifier in obj)) obj[identifier] = defaultvalue; > return obj[identifier]; > } > > const table = {}; > console.log('before getsert:', table.user); // undefined > console.log('during getsert:', Object.getsert(table, 'user', 5)); // 5 > console.log('after getsert:', table.user); // 5 > ``` > > ...I have concerns about such a method's usability though, since a getsert > is far more verbose than a normal get. It'd be more convenient on > Object.prototype (e.g. `table.getsert('user', 5)` ), but I assume that's a > no-go. > > Oh also, I think the proposed syntax would collide with > TypeScript's non-null assertion operator > https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator > -- > I don't know to what degree that's a concern when proposing new JS syntax > > On Sat, Apr 25, 2020 at 3:00 PM Joe Eagar wrote: > >> >> Anyone have ideas on more examples? It’s tempting to make a transpiler >> plugin to see how it works in practice, but I’d like to see more examples >> first. Thanks >> >> On Sat, Apr 25, 2020 at 1:12 PM Jacob Bloom >> wrote: >> >>> Maybe it would be less footgunny to support autovivification in a more >>> class-based way, like Python does? >>> >>> ```javascript >>> class AutoVivArray extends Array { >>> [Symbol.getMissing](identifier) { >>> /* if we're here, identifier is not an ownProperty >>> * and is nowhere on the prototype chain */ >>> this[identifier] = new Whatever(); >>> return this[identifier]; >>> } >>> } >>> ``` >>> >>> Though I can't see how that's much more useful than Proxies besides >>> saving you a little boilerplate >>> >>> On Fri, Apr 24, 2020 at 3:23 PM Thomas Shinnick >>> wrote: >>> >>>> You are describing Perl's autovivification feature. Also possible (in >>>> that syntax) for arrays and mixed object/array chains. I liked it, but many >>>> saw it as a footgun. There was even a compile time module to turn off the >>>> feature, if the coder wanted more caution. Having mentioned Perl I will >>>> assume this is DOA? >>>> >>>> On Fri, Apr 24, 2020, 14:36 Tobias Buschor >>>> wrote: >>>> >>>>> Since we now have the "Optional Chaninig Operator" , perhaps a "Forced >>>>> Chaining Operator" would also be worth considering. >>>>> I, personally, could use it: >>>>> >>>>> let table; >>>>> table!.user!.id!.type = 'int' >>>>> >>>>> will evaluate to: >>>>> >>>>> let table; >>>>> if ( ! ( table instanceOf Object) ) table = {}; >>>>> if ( ! ( table.user instanceOf Object) ) table.user = {}; >>>>> if ( ! ( table.user.id instanceOf Object) ) table.user.id = {}; >>>>> table.user.id.type = 'int'; >>>>> >>>>> Also to be noted: >>>>> Sometimes a fallback to `Object.create(null)` or something other might >>>>> be desirable. >>>>> But since `{}` is syntactical sugar for >>>>> `Object.create(Object.prototype)`, this would be consistent. >>>>> >>>>> ___ >>>>> es-discuss mailing list >>>>> es-discuss@mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>> ___ >>>> es-discuss mailing list >>>> es-discuss@mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>> ___ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Forced Chaining Operator "!."
Is the Perl syntax opt-in like the proposed operator? Or does it happen on all accesses to nulls? If it's opt-in in JS, then it doesn't seem to me that it'd cause too much unexpected behavior, though it could be argued that it's ripe for abuse by new devs trying to avoid errors. Something that might be a more generalized middle ground (and could later assist in transpiling the !. operator) is a "getsert" (?) method in the standard library that takes a default value and sets it on the parent object if that property is currently unset: ```javascript Object.getsert = (obj, identifier, defaultvalue) => { if (!(identifier in obj)) obj[identifier] = defaultvalue; return obj[identifier]; } const table = {}; console.log('before getsert:', table.user); // undefined console.log('during getsert:', Object.getsert(table, 'user', 5)); // 5 console.log('after getsert:', table.user); // 5 ``` ...I have concerns about such a method's usability though, since a getsert is far more verbose than a normal get. It'd be more convenient on Object.prototype (e.g. `table.getsert('user', 5)` ), but I assume that's a no-go. Oh also, I think the proposed syntax would collide with TypeScript's non-null assertion operator https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator -- I don't know to what degree that's a concern when proposing new JS syntax On Sat, Apr 25, 2020 at 3:00 PM Joe Eagar wrote: > > Anyone have ideas on more examples? It’s tempting to make a transpiler > plugin to see how it works in practice, but I’d like to see more examples > first. Thanks > > On Sat, Apr 25, 2020 at 1:12 PM Jacob Bloom > wrote: > >> Maybe it would be less footgunny to support autovivification in a more >> class-based way, like Python does? >> >> ```javascript >> class AutoVivArray extends Array { >> [Symbol.getMissing](identifier) { >> /* if we're here, identifier is not an ownProperty >> * and is nowhere on the prototype chain */ >> this[identifier] = new Whatever(); >> return this[identifier]; >> } >> } >> ``` >> >> Though I can't see how that's much more useful than Proxies besides >> saving you a little boilerplate >> >> On Fri, Apr 24, 2020 at 3:23 PM Thomas Shinnick >> wrote: >> >>> You are describing Perl's autovivification feature. Also possible (in >>> that syntax) for arrays and mixed object/array chains. I liked it, but many >>> saw it as a footgun. There was even a compile time module to turn off the >>> feature, if the coder wanted more caution. Having mentioned Perl I will >>> assume this is DOA? >>> >>> On Fri, Apr 24, 2020, 14:36 Tobias Buschor >>> wrote: >>> >>>> Since we now have the "Optional Chaninig Operator" , perhaps a "Forced >>>> Chaining Operator" would also be worth considering. >>>> I, personally, could use it: >>>> >>>> let table; >>>> table!.user!.id!.type = 'int' >>>> >>>> will evaluate to: >>>> >>>> let table; >>>> if ( ! ( table instanceOf Object) ) table = {}; >>>> if ( ! ( table.user instanceOf Object) ) table.user = {}; >>>> if ( ! ( table.user.id instanceOf Object) ) table.user.id = {}; >>>> table.user.id.type = 'int'; >>>> >>>> Also to be noted: >>>> Sometimes a fallback to `Object.create(null)` or something other might >>>> be desirable. >>>> But since `{}` is syntactical sugar for >>>> `Object.create(Object.prototype)`, this would be consistent. >>>> >>>> ___ >>>> es-discuss mailing list >>>> es-discuss@mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>> ___ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: Forced Chaining Operator "!."
Maybe it would be less footgunny to support autovivification in a more class-based way, like Python does? ```javascript class AutoVivArray extends Array { [Symbol.getMissing](identifier) { /* if we're here, identifier is not an ownProperty * and is nowhere on the prototype chain */ this[identifier] = new Whatever(); return this[identifier]; } } ``` Though I can't see how that's much more useful than Proxies besides saving you a little boilerplate On Fri, Apr 24, 2020 at 3:23 PM Thomas Shinnick wrote: > You are describing Perl's autovivification feature. Also possible (in > that syntax) for arrays and mixed object/array chains. I liked it, but many > saw it as a footgun. There was even a compile time module to turn off the > feature, if the coder wanted more caution. Having mentioned Perl I will > assume this is DOA? > > On Fri, Apr 24, 2020, 14:36 Tobias Buschor > wrote: > >> Since we now have the "Optional Chaninig Operator" , perhaps a "Forced >> Chaining Operator" would also be worth considering. >> I, personally, could use it: >> >> let table; >> table!.user!.id!.type = 'int' >> >> will evaluate to: >> >> let table; >> if ( ! ( table instanceOf Object) ) table = {}; >> if ( ! ( table.user instanceOf Object) ) table.user = {}; >> if ( ! ( table.user.id instanceOf Object) ) table.user.id = {}; >> table.user.id.type = 'int'; >> >> Also to be noted: >> Sometimes a fallback to `Object.create(null)` or something other might be >> desirable. >> But since `{}` is syntactical sugar for >> `Object.create(Object.prototype)`, this would be consistent. >> >> ___ >> 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: Re: Proposal: `await.all {...}` for parallelism
> It seems to me like you are doing block logic without blocks, which I think > increases the chances of bugs. I agree. Without curly braces, it's not always clear when the parallel code is guaranteed to have executed by. The first version of my proposal did something similar: ```javascript const a = await|| doSomethingAsync(); const b = await|| doSomethingElseAsync(); const [aValue, bValue] = await async.all; ``` ...where `async.all` represents something like `Promise.all(promises)`. The problem is, if you forget the `await async.all` then your promises never execute (within the function), so accidentally using `await||` instead of `await` would have the opposite of the intended effect. `async { await|| ... }` sidesteps both of these issues: it makes it clear when the promises have all settled by, and if `await` isn't allowed in the curly brackets then it avoids the "wrong operator" confusion issue as well. > you're not leveraging the existing parallel execution pattern for async > functions (which is just to omit the `await`), so it would seem you > would be increasing learning overhead. If `await||` (or whatever) is learned in conjunction with `async {}` blocks, and is only allowed within them, then it just becomes "this is the syntax for parallelism." And as already stated, you'd need an explicit marker for which expressions are being awaited in parallel for any reasonable transpilation. > `const` and `let` are block-scoped, so this is referring to avoid that block > notation, and then keep coherent with the possibility to directly infer in > current scope references without extra segments / blocks. Yeah, it'd be nice to have a syntax that doesn't create a block scope. But that strikes me as less important than making it obvious where the nondeterminism is. I assume making these braces not create a block scope is unacceptable. And using an alternative bracket (maybe `async [ await|| foo ]`) would be too different from everything else in the language and might read as an array, which discourages using non-expression statements inside it On Wed, Nov 27, 2019 at 9:57 AM Naveen Chawla wrote: > > I don't know that an `await.all { ... }` block would be premature, especially > since it's straightforward, so I can't see it clashing with anything in the > future e.g. on the "observables" front, if that were to become a thing. If > the semantics of `await` were to be extended somehow, then identically and > naturally would the semantics of `await.all { ... }`. > > On Wed, 27 Nov 2019 at 01:43, Isiah Meadows wrote: >> >> Just wanted to drop in and remind people of this by me earlier in the thread: >> https://esdiscuss.org/topic/proposal-await-all-for-parallelism#content-10 >> >> The way things are shaping up, it's starting to look like an ad-hoc version >> of this proposal of mine: >> https://github.com/isiahmeadows/non-linear-proposal >> >> As I stated earlier, I feel it's premature, especially before we figure out >> how observables fit into it all. >> >> On Tue, Nov 26, 2019 at 09:48 Naveen Chawla wrote: >>> >>> If I have, as per your examples, >>> >>> x1 = await||actionAsync1() >>> x2 = await||actionAsync2(x1) //x1 is undefined here, only resolved on the >>> next "non-parallel-await" >>> >>> vs adding a line between the two calls: >>> >>> x1 = await||actionAsync1() >>> let c; >>> x2 = await||actionAsync2(x1) >>> >>> ...does the `let c` automatically break the parallel grouping since it's a >>> non-parallel operation (thereby making x1 defined)? >>> >>> It seems to me like you are doing block logic without blocks, which I think >>> increases the chances of bugs. Also you're not leveraging the existing >>> parallel execution pattern for async functions (which is just to omit the >>> `await`), so it would seem you would be increasing learning overhead. And, >>> you're not really allowing for submitting more sophisticated mixtures of >>> serial async, parallel async and synchronous code for "parallel completion" >>> guarantee, by requiring that parallel calls be "grouped" together in terms >>> of lines of code, almost allowing for nothing beyond the current >>> "Promise.all" pattern, logically. I don't think this is satisfying the >>> original motivation. >>> >>> For a `awail.all { ... }` block, maybe allowing a "return"/"yield" value >>> could neaten up the block scope separation, but maybe that could be left to >>> the "do" expression if that were adopted. But I don't think it's a big >>> sacrifice if neither exist. >>> >>> >>> On Tue, 26 Nov 2019 at 14:14, manuelbarzi wrote: > OK I'm even more confused now. x1 is surely not a resolved value until > all the next "non parallel await" so is it "undefined" until then? as a `const` x1 does not exist until those parallel awaits `await||` (for p1 and p3) are resolved (same for x3). then p2 is resolved after that. what it tries to bring is a simplification of syntax. >
Re: Proposal: `await.all {...}` for parallelism
>>This [current] structure is also just fundamentally different from working >>serially in async/await and it forces you to reason about the problem in a >>specific way. This doesn't appear to be a conscious decision to force good >>code practices > >Actually I'd argue that it is. Doing stuff concurrently is fundamentally >different from doing it serially, and should be reasoned about every time you >use it. I agree that parallelism is different and should be handled with care, but I don't think it follows that the best way to reason about parallelism is the way that `Promise.all` encourages. Making something more complicated doesn't necessarily mean you'll do a better job of reasoning about it. If you think the proposed syntax encourages poorly-reasoned-about code, I'm open to iterating on it to find a syntax that works with the developer to handle parallelism in a safe way, and also doesn't require them to write too much boilerplate code. On Thu, Nov 21, 2019 at 3:16 PM Naveen Chawla wrote: > > Yes of course, I was responding to your proposal and the subsequent email > about it being incompatible with existing JavaScript because "await" on its > own accepts non-promises, so wouldn't return an array of results from an > array of promises, hence why I proposed await.all etc. > > On Thu, 21 Nov 2019 at 18:29, manuelbarzi wrote: >>> >>> I have a solution for that: >>> >>> const promises = [...] >>> await.all promises //returns an array of results >>> await.race promises //returns a single result >> >> >> well, my proposal is exactly that, but doing `await.all` by default with >> just `await`. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Proposal: `await.all {...}` for parallelism
>```javascript >const promises = [...] >await.all promises //returns an array of results >await.race promises //returns a single result >``` One of the goals of this proposal is to simplify the process of collecting the promises in an array and then having to get them out of another array. >Why not just use a combination of `async`/`await` and `.then`? That's an okay solution, though we still end up having to maintain "parallel lists" of promises and values, which I'm hoping to avoid. But you can sidestep them with something like this, which isn't too bad: ```javascript async function initialize() { let foo, bar, baz; await Promise.all([ request('foo.json').then(t => foo = t.data), request('bar.json').then(t => bar = t.data), request('baz.json').then(t => baz = t.data), ]); render(foo, bar, baz); } ``` On Thu, Nov 21, 2019 at 3:29 AM Naveen Chawla wrote: > > I have a solution for that: > > const promises = [...] > await.all promises //returns an array of results > await.race promises //returns a single result > > etc. > > On Thu, 21 Nov 2019 at 09:51, manuelbarzi wrote: >> >> AFAIK `await` can only accept an `expression` as a `Promise`, not other >> thing: >> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await >> >> On Thu, Nov 21, 2019 at 10:46 AM Jacob Bloom >> wrote: >>> >>> >why not just `await` as already is, but supporting an >>> >iterable / array of promises, as `Promise.all` already does >>> >>> `await` can already accept a non-promise, so I believe that'd be >>> breaking syntax if `Array.prototype.then` is set. It also requires >>> collecting the promises in an array, which is what the proposed syntax >>> is trying to avoid. >>> >>> On Thu, Nov 21, 2019 at 2:41 AM Jacob Bloom >>> wrote: >>> > >>> > >Just FYI, I previously suggested a couple things substantially more >>> > >flexible than this >>> > >>> > Ah, thank you for bringing those proposals to my attention. I looked >>> > through the archives for relevant discussions but I must've missed >>> > them. >>> > >>> > It seems like we converged on a similar syntax for what you called >>> > "merging," and the idea that there ought to be a separate syntax for >>> > iteration. I don't know whether that means that this is the right >>> > solution or just the most obvious one, but either way it's encouraging >>> > to know that other people have the same difficulties with the current >>> > syntax and are thinking about the problem. >>> > >>> > >from my experience, committee members are in general >>> > >very hesitant to add syntax for anything that doesn't pay for >>> > >itself well >>> > >>> > Yeah, I figured the bar would be high for new syntax. I've run into >>> > the awkwardness of dealing with distinct parallel tasks several times, >>> > and a few of the people I discussed it with were in the same boat, so >>> > I wrote up this proposal thinking it might have a wide appeal. The >>> > proposed syntax desugars via a relatively simple transformation but >>> > encourages developers to reason about the problem in a completely >>> > different way that I'd argue is more intuitive. Whether the committee >>> > agrees and thinks it justifies a new syntax remains to be seen, but >>> > either way I'm excited to see where this discussion goes (whether it >>> > leads to the proposed syntax, to some other syntax, or to somewhere >>> > else entirely). >>> > >>> > As a side note: thank you to everyone for the thoughtful questions and >>> > responses, I had no idea what to expect from this thread and it's gone >>> > better than I could've hoped for. Thank you for not immediately >>> > shooting down a proposal that looks similar to other proposals before >>> > it. >>> > >>> > On Wed, Nov 20, 2019 at 7:36 PM Isiah Meadows >>> > wrote: >>> > > >>> > > Just FYI, I previously suggested a couple things substantially more >>> > > flexible than this [1] [2] (originated from this [3]), and it mostly >>> > > fell flat due to being highly premature. Anything exclusive to >>> > > promises is unlikely to win as library methods exist for basically all >>> > > use cases and from my experience, committee members ar
Re: Proposal: `await.all {...}` for parallelism
>why not just `await` as already is, but supporting an >iterable / array of promises, as `Promise.all` already does `await` can already accept a non-promise, so I believe that'd be breaking syntax if `Array.prototype.then` is set. It also requires collecting the promises in an array, which is what the proposed syntax is trying to avoid. On Thu, Nov 21, 2019 at 2:41 AM Jacob Bloom wrote: > > >Just FYI, I previously suggested a couple things substantially more > >flexible than this > > Ah, thank you for bringing those proposals to my attention. I looked > through the archives for relevant discussions but I must've missed > them. > > It seems like we converged on a similar syntax for what you called > "merging," and the idea that there ought to be a separate syntax for > iteration. I don't know whether that means that this is the right > solution or just the most obvious one, but either way it's encouraging > to know that other people have the same difficulties with the current > syntax and are thinking about the problem. > > >from my experience, committee members are in general > >very hesitant to add syntax for anything that doesn't pay for > >itself well > > Yeah, I figured the bar would be high for new syntax. I've run into > the awkwardness of dealing with distinct parallel tasks several times, > and a few of the people I discussed it with were in the same boat, so > I wrote up this proposal thinking it might have a wide appeal. The > proposed syntax desugars via a relatively simple transformation but > encourages developers to reason about the problem in a completely > different way that I'd argue is more intuitive. Whether the committee > agrees and thinks it justifies a new syntax remains to be seen, but > either way I'm excited to see where this discussion goes (whether it > leads to the proposed syntax, to some other syntax, or to somewhere > else entirely). > > As a side note: thank you to everyone for the thoughtful questions and > responses, I had no idea what to expect from this thread and it's gone > better than I could've hoped for. Thank you for not immediately > shooting down a proposal that looks similar to other proposals before > it. > > On Wed, Nov 20, 2019 at 7:36 PM Isiah Meadows > wrote: > > > > Just FYI, I previously suggested a couple things substantially more > > flexible than this [1] [2] (originated from this [3]), and it mostly > > fell flat due to being highly premature. Anything exclusive to > > promises is unlikely to win as library methods exist for basically all > > use cases and from my experience, committee members are in general > > very hesitant to add syntax for anything that doesn't pay for itself > > well. Similar questions have come up a few times in the past, too, and > > I've commented on two of them. [4] [5] > > > > If anything, I don't feel we know the problem space well enough, and > > the language lacks the primitives needed to really dig into it. (This > > is why I came up with my generator forking strawman. [6]) > > > > [1]: https://github.com/isiahmeadows/non-linear-proposal > > [2]: https://github.com/isiahmeadows/lifted-pipeline-strawman > > [3]: > > https://esdiscuss.org/topic/observable-promise-parallel-control-flow-proposal > > [4]: https://esdiscuss.org/topic/stream-async-await > > [5]: > > https://esdiscuss.org/topic/improved-syntax-for-observable-mapping-and-subscribing > > [6]: https://github.com/isiahmeadows/proposal-generator-fork > > > > - > > > > Isiah Meadows > > cont...@isiahmeadows.com > > www.isiahmeadows.com > > > > On Wed, Nov 20, 2019 at 6:16 PM Jacob Bloom > > wrote: > > > > > > ...strike that, I misread the "but that still waits for the async > > > functions to complete" part. So what you're proposing is that > > > everything functions normally inside the curly braces, but execution > > > doesn't continue until all promises have resolved? So your example > > > would work essentially like this: > > > > > > ```javascript > > > const x = doSomethingAsync(); > > > const y = doSomethingElseAsync(); > > > await x, await y; > > > // all promises are resolved by now, but > > > // still need to use await to unbox the values > > > someFunction(await x, await y); > > > ``` > > > > > > On Wed, Nov 20, 2019 at 3:28 PM Jacob Bloom > > > wrote: > > > > > > > > >Maybe if you drop the "await" in your example: > > > > > > > > > >```javascript > > > > >await.
Re: Proposal: `await.all {...}` for parallelism
>Just FYI, I previously suggested a couple things substantially more >flexible than this Ah, thank you for bringing those proposals to my attention. I looked through the archives for relevant discussions but I must've missed them. It seems like we converged on a similar syntax for what you called "merging," and the idea that there ought to be a separate syntax for iteration. I don't know whether that means that this is the right solution or just the most obvious one, but either way it's encouraging to know that other people have the same difficulties with the current syntax and are thinking about the problem. >from my experience, committee members are in general >very hesitant to add syntax for anything that doesn't pay for >itself well Yeah, I figured the bar would be high for new syntax. I've run into the awkwardness of dealing with distinct parallel tasks several times, and a few of the people I discussed it with were in the same boat, so I wrote up this proposal thinking it might have a wide appeal. The proposed syntax desugars via a relatively simple transformation but encourages developers to reason about the problem in a completely different way that I'd argue is more intuitive. Whether the committee agrees and thinks it justifies a new syntax remains to be seen, but either way I'm excited to see where this discussion goes (whether it leads to the proposed syntax, to some other syntax, or to somewhere else entirely). As a side note: thank you to everyone for the thoughtful questions and responses, I had no idea what to expect from this thread and it's gone better than I could've hoped for. Thank you for not immediately shooting down a proposal that looks similar to other proposals before it. On Wed, Nov 20, 2019 at 7:36 PM Isiah Meadows wrote: > > Just FYI, I previously suggested a couple things substantially more > flexible than this [1] [2] (originated from this [3]), and it mostly > fell flat due to being highly premature. Anything exclusive to > promises is unlikely to win as library methods exist for basically all > use cases and from my experience, committee members are in general > very hesitant to add syntax for anything that doesn't pay for itself > well. Similar questions have come up a few times in the past, too, and > I've commented on two of them. [4] [5] > > If anything, I don't feel we know the problem space well enough, and > the language lacks the primitives needed to really dig into it. (This > is why I came up with my generator forking strawman. [6]) > > [1]: https://github.com/isiahmeadows/non-linear-proposal > [2]: https://github.com/isiahmeadows/lifted-pipeline-strawman > [3]: > https://esdiscuss.org/topic/observable-promise-parallel-control-flow-proposal > [4]: https://esdiscuss.org/topic/stream-async-await > [5]: > https://esdiscuss.org/topic/improved-syntax-for-observable-mapping-and-subscribing > [6]: https://github.com/isiahmeadows/proposal-generator-fork > > - > > Isiah Meadows > cont...@isiahmeadows.com > www.isiahmeadows.com > > On Wed, Nov 20, 2019 at 6:16 PM Jacob Bloom wrote: > > > > ...strike that, I misread the "but that still waits for the async > > functions to complete" part. So what you're proposing is that > > everything functions normally inside the curly braces, but execution > > doesn't continue until all promises have resolved? So your example > > would work essentially like this: > > > > ```javascript > > const x = doSomethingAsync(); > > const y = doSomethingElseAsync(); > > await x, await y; > > // all promises are resolved by now, but > > // still need to use await to unbox the values > > someFunction(await x, await y); > > ``` > > > > On Wed, Nov 20, 2019 at 3:28 PM Jacob Bloom > > wrote: > > > > > > >Maybe if you drop the "await" in your example: > > > > > > > >```javascript > > > >await.all { > > > >const x = doSomethingAsync(); > > > >//x is just the promise here > > > >} > > > >``` > > > > > > > >...but that still waits for the async functions to complete, I think it > > > >would > > > >cause fewer bugs and would seem to still satisfy the motivation? > > > > > > It doesn't seem like the `await.all` block is doing anything in that > > > case. That code seems equivalent to this: > > > > > > ```javascript > > > const x = doSomethingAsync(); > > > myFunction(await x) > > > ``` > > > > > > >```javascript > > > >await.all { > > > > const x = await doSomethingAsync(); > > > > //x is still undefined here! > &g
Re: Proposal: `await.all {...}` for parallelism
...strike that, I misread the "but that still waits for the async functions to complete" part. So what you're proposing is that everything functions normally inside the curly braces, but execution doesn't continue until all promises have resolved? So your example would work essentially like this: ```javascript const x = doSomethingAsync(); const y = doSomethingElseAsync(); await x, await y; // all promises are resolved by now, but // still need to use await to unbox the values someFunction(await x, await y); ``` On Wed, Nov 20, 2019 at 3:28 PM Jacob Bloom wrote: > > >Maybe if you drop the "await" in your example: > > > >```javascript > >await.all { > >const x = doSomethingAsync(); > >//x is just the promise here > >} > >``` > > > >...but that still waits for the async functions to complete, I think it would > >cause fewer bugs and would seem to still satisfy the motivation? > > It doesn't seem like the `await.all` block is doing anything in that > case. That code seems equivalent to this: > > ```javascript > const x = doSomethingAsync(); > myFunction(await x) > ``` > > >```javascript > >await.all { > > const x = await doSomethingAsync(); > > //x is still undefined here! > >} > >``` > > You bring up a good point about scoping and race conditions. It's a > little tricky since the curly braces create a block scope but none of > the parallel statements should be allowed to access each-other's > variables, it's almost like each statement should have its own scope. > Maybe it'd be better to have a syntax that ensures a set of curly > braces for each parallel task? Async do-expressions could be a good > solution (assuming they'd work kind of like an async IIFE): > > ```javascript > async function initialize() { > let foo, bar, baz; > await Promise.all([ > async do { foo = (await request('foo.json')).data }, > async do { bar = (await request('bar.json')).data }, > async do { baz = (await request('baz.json')).data }, > ]); > render(foo, bar, baz); > } > ``` > > (this is also a less drastic syntax change that piggybacks on an > existing proposal) > > On Wed, Nov 20, 2019 at 11:50 AM Bergi wrote: > > > > Hello! > > > > > This [current] structure is also just fundamentally different from working > > > serially in async/await and it forces you to reason about the problem > > > in a specific way. This doesn't appear to be a conscious decision to > > > force good code practices > > > > Actually I'd argue that it is. Doing stuff concurrently *is* > > fundamentally different from doing it serially, and should be reasoned > > about every time you use it. > > > > kind regards, > > Bergi > > ___ > > 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: Proposal: `await.all {...}` for parallelism
>Maybe if you drop the "await" in your example: > >```javascript >await.all { >const x = doSomethingAsync(); >//x is just the promise here >} >``` > >...but that still waits for the async functions to complete, I think it would >cause fewer bugs and would seem to still satisfy the motivation? It doesn't seem like the `await.all` block is doing anything in that case. That code seems equivalent to this: ```javascript const x = doSomethingAsync(); myFunction(await x) ``` >```javascript >await.all { > const x = await doSomethingAsync(); > //x is still undefined here! >} >``` You bring up a good point about scoping and race conditions. It's a little tricky since the curly braces create a block scope but none of the parallel statements should be allowed to access each-other's variables, it's almost like each statement should have its own scope. Maybe it'd be better to have a syntax that ensures a set of curly braces for each parallel task? Async do-expressions could be a good solution (assuming they'd work kind of like an async IIFE): ```javascript async function initialize() { let foo, bar, baz; await Promise.all([ async do { foo = (await request('foo.json')).data }, async do { bar = (await request('bar.json')).data }, async do { baz = (await request('baz.json')).data }, ]); render(foo, bar, baz); } ``` (this is also a less drastic syntax change that piggybacks on an existing proposal) On Wed, Nov 20, 2019 at 11:50 AM Bergi wrote: > > Hello! > > > This [current] structure is also just fundamentally different from working > > serially in async/await and it forces you to reason about the problem > > in a specific way. This doesn't appear to be a conscious decision to > > force good code practices > > Actually I'd argue that it is. Doing stuff concurrently *is* > fundamentally different from doing it serially, and should be reasoned > about every time you use it. > > kind regards, > Bergi > ___ > 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: Proposal: `await.all {...}` for parallelism
Regarding parallel for-loops: I'd consider that a separate problem. You'd want parallel for-loops for things like requests to the same API, where each promise is handled the same way. `await.all` is more for handling disparate tasks in parallel without having to resort to thinking in terms of arrays and iteration. On Tue, Nov 19, 2019 at 10:27 PM Guy Bedford wrote: > > Typically I find I want to loop over an iterator of items and apply a > function body of work on them in parallel. > > So it would be nice to support full blocks of statements that can do this > work in parallel, instead of relying on just expressions or functions to > achieve this. > > Extending for loops to have a parallel form is another option (I seem to > recall something similar brought up before here): > > ``` > for await.all (const entry of entries) { > await doWork(entry); > } > ``` > > Whether async iteration should be supported or treated as sync or parallel is > another question though, and possibly a confusion of the form. > > On Tue, 19 Nov 2019 at 23:20, Jordan Harband wrote: >> >> If we have `await.all`, what about `await.race`, `await.allSettled`, >> `await.any`? >> >> On Tue, Nov 19, 2019 at 7:45 PM Jacob Bloom wrote: >>> >>> To simplify the problem of working with promises in parallel, I >>> propose this new syntax: >>> >>> ```javascript >>> async function initialize() { >>> let foo, bar, baz; >>> await.all { >>> foo = (await request('foo.json')).data; >>> bar = (await request('bar.json')).data; >>> baz = (await request('baz.json')).data; >>> } >>> render(foo, bar, baz); >>> } >>> ``` >>> >>> Each child statement of the curly braces is evaluated in parallel and >>> execution resumes when they've all resolved. >>> >>> **The Problem:** with current syntax, the above function would >>> probably look something like this: >>> >>> ```javascript >>> async function initialize() { >>> const [ >>> { data: foo }, // renaming response.data => foo >>> { data: bar }, >>> { data: baz }, >>> ] = await Promise.all([ >>> request('foo.json'), >>> request('bar.json'), >>> request('baz.json'), >>> ]); >>> render(foo, bar, baz); >>> } >>> ``` >>> >>> For this kind of use case, `Promise.all` leads to "parallel lists" of >>> promises and their return values, which must be kept in sync. Using >>> those values either requires (sometimes deep) destructuring or >>> temporary variables. >>> >>> This structure is also just fundamentally different from working >>> serially in async/await and it forces you to reason about the problem >>> in a specific way. This doesn't appear to be a conscious decision to >>> force good code practices, it's just a limitation that falls naturally >>> out of the current syntax. Thus, we have an opportunity to shift some >>> of the burden back to the language with this new syntax. >>> >>> Here's the full proposal: >>> https://github.com/mrjacobbloom/proposal-await-all -- let me know what >>> you think! >>> ___ >>> 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: Proposal: `await.all {...}` for parallelism
Regarding the other `Promise` methods, this syntax could certainly extend to all of them (that's part of the reason I chose this syntax, to leave that option open). `await.any` and `await.race` would work analogously to `await.all`, but since we're no longer dealing with return values there's no good way to get the value that won the race. This is fine as long as you're not dependent on that value and only care about executing some code as soon as the race is won. The best way I can think of to get the winning value is something like this: ```javascript async function myFunc() { let value1, value2; await.any { value1 = await foo; value2 = await bar; } const firstResult = value1 || value2; // could also use ?? } ``` ...which isn't any easier than using `Promise.any`. `await.allSettled` would, in many cases, be the same as `Promise.all` except it would also swallow errors. I'd have to think more about its use cases but it could be implemented the same way. On Tue, Nov 19, 2019 at 9:20 PM Jordan Harband wrote: > > If we have `await.all`, what about `await.race`, `await.allSettled`, > `await.any`? > > On Tue, Nov 19, 2019 at 7:45 PM Jacob Bloom wrote: >> >> To simplify the problem of working with promises in parallel, I >> propose this new syntax: >> >> ```javascript >> async function initialize() { >> let foo, bar, baz; >> await.all { >> foo = (await request('foo.json')).data; >> bar = (await request('bar.json')).data; >> baz = (await request('baz.json')).data; >> } >> render(foo, bar, baz); >> } >> ``` >> >> Each child statement of the curly braces is evaluated in parallel and >> execution resumes when they've all resolved. >> >> **The Problem:** with current syntax, the above function would >> probably look something like this: >> >> ```javascript >> async function initialize() { >> const [ >> { data: foo }, // renaming response.data => foo >> { data: bar }, >> { data: baz }, >> ] = await Promise.all([ >> request('foo.json'), >> request('bar.json'), >> request('baz.json'), >> ]); >> render(foo, bar, baz); >> } >> ``` >> >> For this kind of use case, `Promise.all` leads to "parallel lists" of >> promises and their return values, which must be kept in sync. Using >> those values either requires (sometimes deep) destructuring or >> temporary variables. >> >> This structure is also just fundamentally different from working >> serially in async/await and it forces you to reason about the problem >> in a specific way. This doesn't appear to be a conscious decision to >> force good code practices, it's just a limitation that falls naturally >> out of the current syntax. Thus, we have an opportunity to shift some >> of the burden back to the language with this new syntax. >> >> Here's the full proposal: >> https://github.com/mrjacobbloom/proposal-await-all -- let me know what >> you think! >> ___ >> 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
Proposal: `await.all {...}` for parallelism
To simplify the problem of working with promises in parallel, I propose this new syntax: ```javascript async function initialize() { let foo, bar, baz; await.all { foo = (await request('foo.json')).data; bar = (await request('bar.json')).data; baz = (await request('baz.json')).data; } render(foo, bar, baz); } ``` Each child statement of the curly braces is evaluated in parallel and execution resumes when they've all resolved. **The Problem:** with current syntax, the above function would probably look something like this: ```javascript async function initialize() { const [ { data: foo }, // renaming response.data => foo { data: bar }, { data: baz }, ] = await Promise.all([ request('foo.json'), request('bar.json'), request('baz.json'), ]); render(foo, bar, baz); } ``` For this kind of use case, `Promise.all` leads to "parallel lists" of promises and their return values, which must be kept in sync. Using those values either requires (sometimes deep) destructuring or temporary variables. This structure is also just fundamentally different from working serially in async/await and it forces you to reason about the problem in a specific way. This doesn't appear to be a conscious decision to force good code practices, it's just a limitation that falls naturally out of the current syntax. Thus, we have an opportunity to shift some of the burden back to the language with this new syntax. Here's the full proposal: https://github.com/mrjacobbloom/proposal-await-all -- let me know what you think! ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Modify Promise.all() to accept an Object as a parameter
What about special handling for Maps? Maybe something like ``` const requests = new Map(); requests.set('reqA', fetch('...')); requests.set('reqB', fetch('...')); const responses = await Promise.all(requests); console.log( responses.get('reqA'), responses.get('reqB'), ); ``` ...which would continue to fail for most objects and would encourage using Map over POJOs for map-like data structures. (Since Maps are iterable, this may break some existing code but I doubt it) On Fri, Oct 11, 2019 at 11:28 AM Bradford Smith wrote: > > Promise.all(Object.values(myObjWithPromiseValues)).then(...) > > On Fri, Oct 11, 2019 at 10:22 AM Jordan Harband wrote: >> >> The current API accepts an *iterable*, which means any object that has >> `Symbol.iterator`, such as an array or a Set. >> >> Throwing when it receives a non-iterable object is an important tool to >> catch bugs. If Promise.all was made to accept a non-iterable object as well, >> I suspect many bugs would go uncaught. >> >> On Fri, Oct 11, 2019 at 10:15 AM Adam Eisenreich wrote: >>> >>> Back when async/await was introduced I struggeled quite a bit with promises >>> arrays that have conditional promises. RxJS is moving from array only >>> support in theirs operators to objects too, there seems to be an actual >>> trend going on. Is there any reason against? >>> ___ >>> es-discuss mailing list >>> es-discuss@mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >> >> ___ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss > > ___ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Re: Proposal: native XML object support.
> And things such as E4X already exist. Building on that, JSX is just a code transformation that can be used without React. You can swap React out for another compatible library with a pragma: https://babeljs.io/docs/en/next/babel-plugin-transform-react-jsx#pragma -- JSX + a React-like library that creates vanilla DOM elements could be used to achieve a lot of the requested functionality On Sat, May 18, 2019 at 4:01 AM ViliusCreator wrote: > > XML in JS without React could totally bring usage in Node js, not only JS. > For example, you could pass XML object as parameter to website from server > and server would change it to right way, so XML object would be turned to > HTML element. > However, in non web-development environment, it would have no usage. Since > sometimes Node js is used for general-purpose and not web-development, XML > would be practically useless and JSON would be used. And things such as E4X > already exist. > The benefit of XML is that you can do `d `(which is > equivalent to > > ```json > { > ‘//name’: ‘a’, > ‘//inner’: [‘d ’, {...}], > b: ‘c’ > } > ```) and it’s more readable than JSON version of it.` > > > Virus-free. www.avast.com > ___ > 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