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, Exception
s.
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
Keyword | Description |
---|---|
perform | Initiates an effect. The current function halts, and later resumes when an effect handler resume s |
handle | try/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 |
recall | Recalls the previously halted function, who called perform . |
Getting started
There are two ways to get started:
- Try our editor and examples online, now!
- (pending) Install effects into your javascript or typescript project
References
Reference | Description |
---|---|
Source code | github.com/effectsjs/effectsjs |
Dan's Conceptualization | Algebraic 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!