From 7256089bd0f3dff632ffb68218a7680818066446 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 07:08:32 -0500 Subject: [PATCH 1/9] Added the FAQ section --- www/docs/faq.mdx | 52 +++++++++++++++++++++++++++++++++++++++++ www/docs/structure.json | 1 + 2 files changed, 53 insertions(+) create mode 100644 www/docs/faq.mdx diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx new file mode 100644 index 00000000..ff3a6c2f --- /dev/null +++ b/www/docs/faq.mdx @@ -0,0 +1,52 @@ +This page covers questions users of Effection ask as they go through the journey +of learning Effection. + +## Why can't I `yield*` to a promise? + +In TypeScript, if you tried to `yield* Promise.resolve(42)`, TypeScript compiler will +throw an error `Type 'Promise' must have a '[Symbol.iterator]()' method that returns an iterator.`. +In JavaScript, it will just not work. This happens because neither TypeScript nor JavaScript runtimes know how to +convert a Promise into an iterator, which is required for yield* to work. + +We opted to choose not to monkey patch the Promise prototype by adding the integration needed to make `yield*` +promise work, because this would compromise the guarantees that are described in [Thinking in Effection] +by bluring the line about where the guarantees apply. Right now, the line is very clear, anything on the +right side of `yield*` is guaranteed to exit fully and never outlive the operation where the `yield*` was +called. We can't make these guarantees with Promises for the reasons described in [The Await Event Horizon] +blog post. + +## Can I make Promise compatible with `yield*`? + +Yes, by monkeypatching the Promise prototype. Monkeypatching in JavaScript refers to the practice +of modifying or extending existing objects or functions at runtime, typically without changing their +original source code. It's considered risky because it breaks the expectations that developers maintaining +and running the code have of the JavaScript runtime. There are circumstances where the convenience of `yield*` +to promise outweighs the risks. We'll let you make the decision where those circumstances are for you. + +You can use the following code to monkeypatch Promise if you choose to do so. You can put this code into a module +and import it when you want this effect. + +```typescript +import { call, type Effect } from "effection"; + +declare global { + interface Promise { + [Symbol.iterator](): Iterator, T, unknown>; + } +} + +Promise.prototype[Symbol.iterator] = function*() { + return yield* call(() => this); +} +``` + +## Why can't I use `call(Promise.resolve(42))` anymore? + +In Effection v3, it was possible to `yield* call(Promise.resolve(42))` but we removed this in Effection v4 +because we wanted to align call closer to `Function.prototype.call`. You can still use +`yield* call(() => Promise.resolve(42))` and `yield* call(async function() {})`. In v4, we plan to ship +a new function called `when` which will take a promise and wrap it in a constructor for convenience. + + +[The Await Event Horizon]: https://frontside.com/blog/2023-12-11-await-event-horizon/ +[Thinking in Effection]: thinking-in-effection \ No newline at end of file diff --git a/www/docs/structure.json b/www/docs/structure.json index 09b1640a..9e748998 100644 --- a/www/docs/structure.json +++ b/www/docs/structure.json @@ -17,6 +17,7 @@ ["context.mdx", "Context"] ], "Advanced": [ + ["faq.mdx", "FAQ"], ["scope.mdx", "Scope"], ["processes.mdx", "Processes"] ] From a2125af4fe9408181ee09e40fd0e994e167633dd Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 07:25:35 -0500 Subject: [PATCH 2/9] Added links directly --- www/docs/faq.mdx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index ff3a6c2f..989b012a 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -9,10 +9,10 @@ In JavaScript, it will just not work. This happens because neither TypeScript no convert a Promise into an iterator, which is required for yield* to work. We opted to choose not to monkey patch the Promise prototype by adding the integration needed to make `yield*` -promise work, because this would compromise the guarantees that are described in [Thinking in Effection] +promise work, because this would compromise the guarantees that are described in [Thinking in Effection](./thinking-in-effection) by bluring the line about where the guarantees apply. Right now, the line is very clear, anything on the right side of `yield*` is guaranteed to exit fully and never outlive the operation where the `yield*` was -called. We can't make these guarantees with Promises for the reasons described in [The Await Event Horizon] +called. We can't make these guarantees with Promises for the reasons described in [The Await Event Horizon](https://frontside.com/blog/2023-12-11-await-event-horizon/) blog post. ## Can I make Promise compatible with `yield*`? @@ -46,7 +46,3 @@ In Effection v3, it was possible to `yield* call(Promise.resolve(42))` but we re because we wanted to align call closer to `Function.prototype.call`. You can still use `yield* call(() => Promise.resolve(42))` and `yield* call(async function() {})`. In v4, we plan to ship a new function called `when` which will take a promise and wrap it in a constructor for convenience. - - -[The Await Event Horizon]: https://frontside.com/blog/2023-12-11-await-event-horizon/ -[Thinking in Effection]: thinking-in-effection \ No newline at end of file From ec6b3773b922750ddf7d6361c9f785798085a8ac Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 10:44:51 -0500 Subject: [PATCH 3/9] Update www/docs/faq.mdx Co-authored-by: Charles Lowell --- www/docs/faq.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index 989b012a..69c63fb6 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -30,9 +30,7 @@ and import it when you want this effect. import { call, type Effect } from "effection"; declare global { - interface Promise { - [Symbol.iterator](): Iterator, T, unknown>; - } + interface Promise extends Operation {} } Promise.prototype[Symbol.iterator] = function*() { From 6bc2e335bed00fd1d49d2ef7370c2b9b837f2820 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 10:45:08 -0500 Subject: [PATCH 4/9] Update www/docs/faq.mdx Co-authored-by: Charles Lowell --- www/docs/faq.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index 69c63fb6..4a185c47 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -33,9 +33,11 @@ declare global { interface Promise extends Operation {} } -Promise.prototype[Symbol.iterator] = function*() { - return yield* call(() => this); -} +Object.defineProperty(Promise.prototype, Symbol.iterator, { + value(): { + return call(() => this)[Symbol.iterator](); + } +}); ``` ## Why can't I use `call(Promise.resolve(42))` anymore? From 0007ee5e8ecafbac8d4f5cc1de0f124f6fc960aa Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 10:45:15 -0500 Subject: [PATCH 5/9] Update www/docs/faq.mdx Co-authored-by: Charles Lowell --- www/docs/faq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index 4a185c47..2930a987 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -5,7 +5,7 @@ of learning Effection. In TypeScript, if you tried to `yield* Promise.resolve(42)`, TypeScript compiler will throw an error `Type 'Promise' must have a '[Symbol.iterator]()' method that returns an iterator.`. -In JavaScript, it will just not work. This happens because neither TypeScript nor JavaScript runtimes know how to +In JavaScript, it will just not work. This happens because neither the TypeScript nor the JavaScript runtimes know how to convert a Promise into an iterator, which is required for yield* to work. We opted to choose not to monkey patch the Promise prototype by adding the integration needed to make `yield*` From 4ad080b74f253c1866dd3ab5ff2a452badea3223 Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 10:45:48 -0500 Subject: [PATCH 6/9] Update www/docs/faq.mdx Co-authored-by: Charles Lowell --- www/docs/faq.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index 2930a987..d3b29adb 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -8,9 +8,8 @@ throw an error `Type 'Promise' must have a '[Symbol.iterator]()' method In JavaScript, it will just not work. This happens because neither the TypeScript nor the JavaScript runtimes know how to convert a Promise into an iterator, which is required for yield* to work. -We opted to choose not to monkey patch the Promise prototype by adding the integration needed to make `yield*` -promise work, because this would compromise the guarantees that are described in [Thinking in Effection](./thinking-in-effection) -by bluring the line about where the guarantees apply. Right now, the line is very clear, anything on the +While adding the integration to make `yield*` work with a promise is possible by monkey patching the `Promise` prototype, we opted not to do so. Not only is monkey patching a global object from a library considered bad form, but it would also compromise the guarantees that are described in [Thinking in Effection](./thinking-in-effection) +by blurring the line about where those guarantees apply. Right now, the line is very clear: anything on the right side of `yield*` is guaranteed to exit fully and never outlive the operation where the `yield*` was called. We can't make these guarantees with Promises for the reasons described in [The Await Event Horizon](https://frontside.com/blog/2023-12-11-await-event-horizon/) blog post. From 5f044d0e2094b6f6f1b5648f771ab5177b2b644e Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 10:46:24 -0500 Subject: [PATCH 7/9] Update www/docs/faq.mdx Co-authored-by: Charles Lowell --- www/docs/faq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index d3b29adb..6cd591c5 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -16,7 +16,7 @@ blog post. ## Can I make Promise compatible with `yield*`? -Yes, by monkeypatching the Promise prototype. Monkeypatching in JavaScript refers to the practice +Yes. You can `yield*` to a `Promise` by monkey patching the `Promise` prototype. "Monkey patching" in JavaScript refers to the practice of modifying or extending existing objects or functions at runtime, typically without changing their original source code. It's considered risky because it breaks the expectations that developers maintaining and running the code have of the JavaScript runtime. There are circumstances where the convenience of `yield*` From fb14e2afc080fc1d371da5fafe90768891ee451c Mon Sep 17 00:00:00 2001 From: Taras Mankovski Date: Tue, 28 Jan 2025 12:59:05 -0500 Subject: [PATCH 8/9] Update www/docs/faq.mdx Co-authored-by: Charles Lowell --- www/docs/faq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index 6cd591c5..a322d9a6 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -26,7 +26,7 @@ You can use the following code to monkeypatch Promise if you choose to do so. Yo and import it when you want this effect. ```typescript -import { call, type Effect } from "effection"; +import { call, type Operation } from "effection"; declare global { interface Promise extends Operation {} From 403480926604bb3970da6bd27f78a696937c8ac2 Mon Sep 17 00:00:00 2001 From: Charles Lowell Date: Tue, 28 Jan 2025 12:52:54 -0600 Subject: [PATCH 9/9] Update www/docs/faq.mdx --- www/docs/faq.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/www/docs/faq.mdx b/www/docs/faq.mdx index a322d9a6..3cbce1ff 100644 --- a/www/docs/faq.mdx +++ b/www/docs/faq.mdx @@ -29,13 +29,13 @@ and import it when you want this effect. import { call, type Operation } from "effection"; declare global { - interface Promise extends Operation {} + interface Promise extends Operation {} } Object.defineProperty(Promise.prototype, Symbol.iterator, { - value(): { + value() { return call(() => this)[Symbol.iterator](); - } + }, }); ```