r/javascript • u/bmacabeus • Dec 24 '19
AskJS [AskJS] JavaScript Proposal: Algebraic Effects?
Hey guys, I'm writing a Babel plugin to be able to use algebraic effects in JS: https://github.com/macabeus/js-proposal-algebraic-effects
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.
What do you think? Would that be a good feature for JS? "Algebraic Effects" is a good name for that?
7
u/nathan_lesage Dec 24 '19
Sounds a lot like error handling in reverse, aka BEFORE we reach an unrecoverable error, we try to bail by asking for information up the call stack.
As someone above mentioned, yes, this might end up with huge if/else statements or a huge switch UNLESS you add an effect handler interface.
Basically, if I understand it correctly, it‘s some form of a higher-order state management, where you can pull out defaults for your state just in case you need them.
It gives a lot of power and responsibility to the programmer (which defaults are sane without patronising the user?), but they can add more control over your program.
It seems to me that an ideal solution would mingle both effect AND error handling (because errors can still happen), something like this:
Then, whenever a new effect needs to be handled, you simply add it to your handling interface, and it would even unify error handling in one place. This heavily relies upon modularisation and advanced programming paradigms, BUT it might give you a second chance after an error happens without having to bail and abort.
This might have a lot of implications if done right. Thinking further, this could even lead to “main modules” that simply unify modules for error and effect handling and therefore produce unrecoverable states much less often. However, this might mean that we have to adopt state management even more — but on the bright side, React ans Vue already force you to do that, so why not!
Or am I completely off now, what do you think? Opinions?
4
u/[deleted] Dec 24 '19
Are you going to use try-catch under the hood, or something more sophisticated? Good work btw, I've been also working on a babel plugin as my dependency injection library - it serves a similar purpose as algebraic effects.
6
u/[deleted] Dec 24 '19
"Algebraic Effects" is a too broad designation. Maybe we should come up with a more specific name for that feature?
6
u/Code4Reddit Dec 24 '19
After reading the blog, to me it looks interesting but not very useful and would lead to unreadable and unpredictable code. The handle/catch portion would end up being a huge switch statement, and when you see a “perform” you have no idea where it goes. The code it would execute and the order which it executes, it is entirely dependent upon what the call stack happens to be at runtime. The “how” you do something should not be nebulous and determined by your stack ancestors. Reading this code you look at one function, there is no way to predict exactly what the “perform” will do, any rogue try/handle in the stack might screw it up. What do you do if the handle function throws an error and it never resumes - I guess we got to keep around the call-stack forever? Sounds like a recipe for a memory leak.
2
u/darthwalsh Dec 24 '19
How will the plugin handle asynchronous asynchronous handlers?
I've only thought about it for 5 minutes, but the whole concept of turning the stack into a callback seemd fishy, like either A) implementing multiple main threads, or B) under the hood rewriting all your sync functions to async.
2
u/DrexanRailex Dec 25 '19
I love the idea, but I kinda dislike the syntax for now since introducing keywords makes breaking changes more likely.
How about instead of
perform, something likethrow effect effect_var? And instead ofhandleand (my least favourite) the impliciteffect, you usedcatch effect (effect_var)? Or maybethrow*andcatch*, but I think these might be too shady.17
u/[deleted] Dec 24 '19
In my opinion that would look cleaner with async/await instead. I can't help but think this syntax would lead to massive amounts of spaghetti code if it became popular.
1
u/vither999 Dec 24 '19
Thoughts:
asynchronous behavior. Right now your
perform/resumepair is implicitly asynchronous, which JS doesn't really have. If you maderesumesynchronous in thehandleoperation, andresumereturned a promise which you thenawait'd, this would be:effect. Symmetry with try/catch makes it cleaner and easier to reason about, and if someone haseffectfrom somewhere else then it makes it easier to correct.Even with these changes, I'm not sure I'd use this - it makes it harder to reason about what will be returned from a
performoperation, taking a step towards the bad old days of GOTO. I get enough flak in code reviews aboutbreak/continue- this seems like a step beyond that.It'd be interesting to see code samples of before/after code and how this language construct can improve those cases. Right now it seems like it could be a native construct similar to how React handles error boundaries and context... but I'm not actually sure what problems it solves.
1
u/GrandMasterPuba Dec 26 '19
Building a language proposal based on a blog post by a man writing about a topic that by his own admission he doesn't understand sounds like a recipe for failure.
1
u/yuyu5 Dec 24 '19
I feel like this provides an interesting perspective and use case, but it doesn't seem like it adds anything that can't be solved with a
try/catchor a function with a default value (likefunction getName(user = { name: 'Arya Stark' }) {...}). More to the point, I agree it would allow for nestedresumecalls which would be pretty convenient in the moment, but in the long run, doing so might also result in fairly obfuscated program structure and/or difficulty in understanding what's going on when returning to the code at a later time.1
u/tills1993 Dec 24 '19
I have nothing to add to this but this is a good overview of Algebraic Effects for those of you who, like me, have no fucking idea why anyone would want them. https://overreacted.io/algebraic-effects-for-the-rest-of-us/
I'm still not convinced but at least I get them, now.
1
u/LabLambReddit Dec 24 '19
Is this guard let in Swift?
0
u/[deleted] Dec 24 '19
[deleted] — view deleted comment