diff --git a/README.md b/README.md index bfa31928..abd2154c 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ > 📐Let there be algebraic effects in JavaScript

- +

# Why? @@ -27,22 +27,24 @@ Again, the syntax needs to be improved. But at this moment we have: - **Expression `perform `** You could use this keyword inside of any function (not arrow functions!) in order to launch an effect.
-Similar to `throw`, it'll search for the closest `try/handle` at call stack to perform an effect passing `` as the effect name. Unlike `throw`, `perform` is an expression and will return a value. +Similar to `throw`, it'll search for the closest `try/handle` at call stack to perform an effect passing `` as the effect name. Unlike `throw`, `perform` is an expression and will return a value to continue running the code. ```js if (name === null) { name = perform 'ask_name' + console.log(name) // after evaluate perform, will run this line } ``` - **Block `handle` at `try`** -Just like the `catch` block, you should use it to handle the effect launched inside of the `try` block. In the scope of `handle`, it is implicitly injected a variable called `effect`, with the `` from `perform`. +Just like the `catch` block, you should use it to handle the effect launched inside of the `try` block.
+And again as like `catch` block, this block has a parameter to bind the `` used at `perform`. ```js try { ... -} handle { +} handle (effect) { if (effect === 'ask_name') { ... } @@ -51,11 +53,16 @@ try { - **Statement `resume`** -It should be used inside of the `handle` block in order to resume the `perform` expression, returning a value. +It should be used inside of the `handle` block in order to resume the `perform` expression, returning a value.
+It must be used inside of `handle` block and must be in `handle` block directly. ```js -if (effect === 'ask_name') { - resume 'Arya Stark' +try { + ... +} handle (effect) { + if (effect === 'ask_name') { + resume 'Arya Stark' + } } ``` @@ -63,9 +70,8 @@ One of its most powerful features is to use inside a block with an async operati ```js if (effect === 'ask_name') { - setTimeout(() => { - resume 'Arya Stark'; - }, 1000); + await wait(1000) + resume 'Arya Stark' } ``` @@ -92,11 +98,78 @@ const arya = { name: null }; try { displayNameCapitalized(arya); // doesn't need to use @@ -} handle { +} handle (effect) { ... } ``` +### Edge cases + +- no `resume` + +Since `perform` is an expression, it always return a value. If `resume` wasn't called after a perform, it'll be `undefined`: + +```js +function sayName () { + const name = perform 'a_typo_error' + console.log(name) // undefined +} + +try { + sayName() +} handle (effect) { + if (effect === 'ask_name') { + resume 'Arya Stark' + } +} +``` + +- no `try/handle` block + +If a `perform` is called without a `try/handle`, an expection will be launched. + +```js +function sayName () { + const name = perform 'ask_name' // will throw Error('Unhandled effect') + console.log(name) +} + +sayName() +``` + +- nested `try/handle` (not implemented yet) + +If you have two or more nested `try/handle`, you'll need to call `resume` on `handle` block + +```js +function sayNameAndAge () { + const name = perform 'ask_name' + const age = perform 'ask_age' + console.log(name, age) // 'Arya Stark 25' +} + +function wrapperAgeEffect () { + try { + sayNameAndAge() + } handle (effect) { + if (effect === 'ask_age') { + resume 25 + } + + const result = perform effect + return result + } +} + +try { + wrapperAgeEffect() +} handle (effect) { + if (effect === 'ask_name') { + resume 'Arya Stark' + } +} +``` + # How to run 1 - Clone this repo: