6 ms·
In this case, I'd like to write blocking-style code. longjmp, however, is a crucial missing facility in JS. Emacs relies on it heavily in its design -- it's ho
by sillysaurus3 8y ago
In this case, I'd like to write blocking-style code.
longjmp, however, is a crucial missing facility in JS. Emacs relies on it heavily in its design -- it's how catch / throw work, and it's why you can do things like
(catch 'foo
(map (fn (x)
(if (= x 42) (throw 'foo x)))
values))
Without longjmp, you can't do that. Just as you can't in JS.
So what? Well, that means you can't write emacs, because you're limited to what JS provides you. An entire class of software is beyond your ability to write, because you cannot provide the same features that other runtimes give.
This gets me started on the lack of any kind of reasonable error definitions in JS. In elisp, you define errors. Imagine you want to write some code that parses some parens -- it turns "(a b (c))" into ["a", "b", ["c"]]. What do you do when your program encounters "(a b" and then the end of the string? Throw a scan error!
Not in JS. It's considered poor manners to throw errors to the people using your library. Worse, it's a pain in the ass for users to catch and respond to errors. If you use someone's library, you usually don't expect to have to wrap it in a try-catch. And the code is massive:
try { operation } catch (e) { if (e instanceof ScanError) { do something else } }
Contrast that with elisp:
(condition-case nil
operation
(scan-error do something else))
There's no contest. It's way easier to write the latter than to use the tools JS gives you. But it's a cultural difference, and culture is slow to change.
That's why webassembly at least gives an escape hatch.
- millstone 8y ago> Well, that means you can't write emacs, because you're limited to what JS provides you Well JS does provide this via exceptions. Second it's totally crazy that emacs depends on longjmp, which is an insane decades-old wart that ought to just quietly die. Third...does web assembly even support longjmp? I'm pretty sure it does not. > That's why webassembly at least gives an escape hatch. Escape hatch from...writing five lines instead of three?
- sillysaurus3 8y agofunction foo() { return doSomething(); } async function doSomething() { ... throw ScanError(); } Spot the bug? That's an async function. Every JS programmer worth their salt will tell you how many times they've been annoyed to discover a missing await, and that the promise is failing mostly-silently (or worse, it works by accident until it doesn't, since that code will work fine most of the time). Well JS does provide this via exceptions. Second it's totally crazy that emacs depends on longjmp It's not crazy. function bar() { [1,2,3].forEach(x => { if (x == 2) /* return from bar...? */ } } Why can't you write this code? I mean you "can": function bar() { let tag = []; try { [1,2,3].forEach(x => { if (x == 2) { tag.value = x; throw tag; } } } catch (e) { if (e === tag) { return e.value; } } But holy crap that's terrible. EDIT: I also forgot to rethrow the error, showing just how easy it is to screw up. Just write it as a for loop, then. Well sure, except for the hundreds of libraries that don't support that style. What do you do when you want to return prematurely from the iterator functions you pass to them? Now you can't just make a for loop unless they provide Symbol.iterator. And 9 times out of 10 they give you a promise, meaning you're forced to convert your code to async style. It's a huge mess, and longjmp saves you a lot of headaches in disciplined situations. Every tool has its place, and it's strange to argue that a computer should be able to do less, not more. The goal is to save you time in the long run. And those 5 lines better be exactly right, or you'll waste a lot.
- gear54rus 8y agojust use one of myriad array methods available, like "find" for this case "can't write some class of software" is just wrong, is all
- gpderetta 8y agoI'm prettty sure you can implement a elisp (or any language with continuations) interpreter/compiler without longjump in the host language.
- sillysaurus3 8y agoYes, but it can’t easily interop with the host language. Elisp saves the stack, which you can’t do in JS. That means you can’t cross JS -> elisp boundaries with your longjmp without some pretty awful hacks.
- gpderetta 8y agoYou cannot longjmp across 'native' stackframes (which mightor might not be a big limitation), but otherwise interop should be fine. The native interpreter stack is always around to be used to run native function calls.