All Projects β†’ macabeus β†’ Js Proposal Algebraic Effects

macabeus / Js Proposal Algebraic Effects

πŸ“Let there be algebraic effects in JS

Programming Languages

javascript
184084 projects - #8 most used programming language
js
455 projects
proposal
26 projects

Projects that are alternatives of or similar to Js Proposal Algebraic Effects

Sowing Machine
🌱A React UI toolchain & JSX alternative
Stars: ✭ 64 (-41.82%)
Mutual labels:  babel, babel-plugin
Babel Plugin Optimize Clsx
Babel plugin to optimize the use of clsx, classnames, and other libraries with a compatible API
Stars: ✭ 80 (-27.27%)
Mutual labels:  babel, babel-plugin
Astexplorer.app
https://astexplorer.net with ES Modules support and Hot Reloading
Stars: ✭ 65 (-40.91%)
Mutual labels:  babel, babel-plugin
Babel Plugin Css Prop
Babel plugin to transpile `css` prop to a styled component. (Experimental)
Stars: ✭ 56 (-49.09%)
Mutual labels:  babel, babel-plugin
Generator Babel Plugin
Babel Plugin generator for Yeoman
Stars: ✭ 88 (-20%)
Mutual labels:  babel, babel-plugin
Tinker.macro
Evaluate Laravel code at build-time, via Laravel Tinker
Stars: ✭ 56 (-49.09%)
Mutual labels:  babel, babel-plugin
Babel Plugin Jsx Adopt
Stars: ✭ 94 (-14.55%)
Mutual labels:  babel, babel-plugin
Babel Plugin Styled Components
Improve the debugging experience and add server-side rendering support to styled-components
Stars: ✭ 878 (+698.18%)
Mutual labels:  babel, babel-plugin
Modify Babel Preset
πŸ’« Create a modified babel preset based on an an existing preset.
Stars: ✭ 85 (-22.73%)
Mutual labels:  babel, babel-plugin
Compiled
A familiar and performant compile time CSS-in-JS library for React.
Stars: ✭ 1,235 (+1022.73%)
Mutual labels:  babel, babel-plugin
Babel Plugin Root Import
Add the opportunity to import modules by the root path
Stars: ✭ 1,084 (+885.45%)
Mutual labels:  babel, babel-plugin
Jsx Control Statements
Neater If and For for React JSX
Stars: ✭ 1,305 (+1086.36%)
Mutual labels:  babel, babel-plugin
Xwasm
[Work In Progress] WebAssembly Packager and WASM tooling for modern frontend
Stars: ✭ 45 (-59.09%)
Mutual labels:  babel, babel-plugin
Babel Plugin Partial Application
[DEPRECATED] Please use https://github.com/citycide/param.macro
Stars: ✭ 60 (-45.45%)
Mutual labels:  babel, babel-plugin
Postjss
Use the power of PostCSS in compiling with JSS
Stars: ✭ 40 (-63.64%)
Mutual labels:  babel, babel-plugin
Babel Plugin Captains Log
Babel plugin that injects helpful details into console statements
Stars: ✭ 80 (-27.27%)
Mutual labels:  babel, babel-plugin
Htm
Hyperscript Tagged Markup: JSX alternative using standard tagged templates, with compiler support.
Stars: ✭ 7,299 (+6535.45%)
Mutual labels:  babel, babel-plugin
Babel Plugin Transform React Remove Prop Types
Remove unnecessary React propTypes from the production build. 🎈
Stars: ✭ 890 (+709.09%)
Mutual labels:  babel, babel-plugin
Catom
A 0 runtime CSS in JS library
Stars: ✭ 84 (-23.64%)
Mutual labels:  babel, babel-plugin
Idx.macro
a 'babel-macros' version of 'babel-plugin-idx'
Stars: ✭ 90 (-18.18%)
Mutual labels:  babel, babel-plugin

js-proposal-algebraic-effects

πŸ“Let there be algebraic effects in JavaScript

Why?

No more function color! Yes one-shot delimited continuation!

What the hell?! Well... I really recommend that you read this blog post by Dan Abramov explaining algebraic effects - and how it could be very useful on our JavaScript code!

This project is a runnable POC with a Babel's "plugin", so you could write some code and taste this new concept in JavaScript. Its features, syntax, and goals are very inspired by Dan Abramov's blog post mentioned above. In short, with algebraic effects, you could separate what from the how and have fewer refactors.

Related:

It's a very simple proof of concept! There is a lot of work to improve this idea, spec, and implementation.

What does it add to the language?

Again, the syntax needs to be improved. But at this moment we have:

  • Expression perform <value>

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 <value> as the effect name. Unlike throw, perform is an expression and will return a value to continue running the code.

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.
And again as like catch block, this block has a parameter to bind the <value> used at perform.

try {
 ...
} handle (effect) {
 if (effect === 'ask_name') {
   ...
 }
}
  • Statement resume

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.

try {
 ...
} handle (effect) {
 if (effect === 'ask_name') {
  resume 'Arya Stark'
 }
}

One of its most powerful features is to use inside a block with an async operation so you could call an async operator without the need to use an async/await operators on the function - that is, less refactors and a function could be sync and async at the same time!

if (effect === 'ask_name') {
 await wait(1000)
 resume 'Arya Stark'
}
  • operator @@

Unfortunately, we still can't inject implicitly the effects inside of a function call outside of the try block, so you should use @@ at a function call that could launch effects.

function getName(user) {
 let name = user.name;
 if (name === null) {
   name = perform 'ask_name';
 }

 return name;
}

function displayNameCapitalized(user) {
 const name = getName@@(user) // need to use @@
 console.log(name.toUpperCase())
}

const arya = { name: null };

try {
 displayNameCapitalized(arya); // doesn't need to use @@
} 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:

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.

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

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:

> git clone [email protected]:macabeus/js-proposal-algebraic-effects.git

2 - Run some commands on Babel:

> cd babel
> make bootstrap
> make watch

3 - So you could compile the sample with:

> cd babel-algebraic-effects
> yarn start

TODO

Check Issues and TODOs.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].