What is it?

Extensions to the javascript language, enabling new control flows that may be well suited to a variety of general purpose programming contexts.

Example

async function main() {
  "use effects";  try {
    const cat = await getCatUrl();
    console.log(cat)
  } handle "fetchJson" with ({ data }) {    recall await fetch(data.url).then(res => res.json())  }
}
async function getCatUrl() {
  const metaCat = perform {    type: "fetchJson",    data: { url: "https://aws.random.cat/meow" }
  };
  return metaCat.file
}
main()

TL;DR - What are Algebraic Effects?

The best way to conceptualize the effect control flow is to expand upon an already well-known programming language construct, Exceptions.

Consider the following example:

const child = () => {
  throw "Hello";
};

const parent = () => {
  child();
  doMoreWork();
};

const main = () => {
  try {
    parent();
  } catch (e) {
    console.log(e);
  }
};

Function calls get pushed onto the call-stack as they are invoked. Normally, after a function completes, its frame is popped off of the call stack and the previous stack frame is resumed. The above example demonstrates an alternative flow:

  • child throws an exception,
  • the exception "bubbles" up the call-stack until a call-site with an exception handler is found.

If you've been programming in a language that offers first-class support for exception handling as outlined above, you're most-likely comfortable with the flow just described.

Now let's tweak our existing mental model for this new concept. Imagine a catch-block that can resume back to the throwing call-site. In the above example, our catch block in main, would recall to child.

This is the crash course for the proposed control flow, and the keywords to facilitate it.

Keywords

KeywordDescription
performInitiates an effect. The current function halts, and later resumes when an effect handler resumes
handletry/handle blocks allow users to specify handlers for effect events, using well-known try/catch-like semantics. try/handle is not compatible with try/catch
recallRecalls the previously halted function, who called perform.

Getting started

There are two ways to get started:

References

ReferenceDescription
Source codegithub.com/effectsjs/effectsjs
Dan's ConceptualizationAlgebraic Effects for the Rest of Us

FAQ

Why do I need to use "use effects"?

The "use effects" directive is not desired for part of the specification. It is a temporary, syntactical necessity to enable the babel compiler to support effectjs at runtime.

Can I perform an effect from within an effect?

Currently, no. In the future, maybe!