If this is a last-ditch resort, then why is the discussion here focussing on that rather than the rest of @kayceesrk’s message, which is a list of techniques to support js compilation for effects? And not just one technique like CPS – but five! It would be nice to see a spirit of adventure with this exciting new feature and the community pitching in with ideas and prototypes to explore how to get jsoo up to speed before effects land in a mainstream OCaml compiler.
The multicore and core OCaml dev teams are pretty busy in the short-term with the rather large amount of work required to get the native ecosystems ported over, so I’d very much welcome efforts in this direction from those interested in the web ecosystem.
Because as can be seen by the discussion in question. No everyone does seem to understand the implication on the user experience of js_of_ocaml which is not so well summarized by:
(P.S. this reply was intended to the general addition to the thread and not a specific reply to @avsm )
Look at Kotlin – it supports JVM/Javascript/Native. See kotlin-stdlib - Kotlin Programming Language (with the various color codes corresponding to the platform) you have this messy matrix of which features/APIs are supported for which platform. As you can imagine it requires a lot of engineering effort to maintain this and test this as each of the platforms that Kotlin runs on keeps evolving and getting more specialized and complex. Without the might of a organized effort (and funding) I doubt that JS/Wasm generation will be a first class citizen for OCaml in the long term.
Even if we can transpile effects from Ocaml bytecode to Javascript (and WASM in the future), its going to be full of edge cases and surprises and debugging problems. It is tough enough to debug JSOO in the browser, imagine throwing non-local control flows into the mix and debugging that.
JSOO came at a lucky time when the OCaml runtime was simple enough that ocaml bytecode could be translated to Javascript without many compatibility issues. That time is over, in my opinion.
OCaml should concentrate on being the best backend platform it needs to be. After having explored this space, I personally see a lot of issues for a JSOO approach going forward. Its too heavyweight. I think something like Rescript (Bucklescript) is more likely to succeed. It would have been great to have a Rescript (Bucklescript) as a first class citizen in the OCaml tree. But that again gives rise to the huge engineering complexity that Kotlin has had to take on and this messy matrix of what works and what does not on the platform you want to emit for, separate standard libraries etc.
So its a good thing in some way that OCaml can aspire to be excellent in a few domains instead of average in many. Javascript/WASM emission is always going to be full of problems – I don’t think OCaml is the answer in the future here, though there might be some cool developments along the way. Just my view…
its going to be full of edge cases and surprises and debugging problems. It is tough enough to debug JSOO in the browser, imagine throwing non-local control flows into the mix and debugging that.
I don’t know about the state of debugging jsoo in the browser, but non-local control flow and debugging doesn’t need to be hard. For one, Multicore OCaml produces sensible backtraces under non-local control-flow both within the runtime’s own mechanism (such as backtraces with exceptions) and using DWARF (backtraces in gdb and lldb). Yes, Multicore OCaml maintains its own stacks, which make the job easier. I believe C# and Kotlin (which is mentioned in the parent comment), which turn the function in “state machines” (essentially a form of CPS), are also able to recover backtraces for coroutines and async-await. It is a bit of work, but that’s work that is already being done in many other languages.
No everyone does seem to understand the implication on the user experience of js_of_ocaml which is not so well summarized by:
I don’t see why this is harder than what the state of jsoo is currently for the OCaml standard library. There is no syntactic addition for effect handlers in OCaml 5.0. There is just a new stdlib module Effect_handlers that adds effect handler functionality. Just like how Weak and Sys models are not supported, Effect_handlers would be unsupported until jsoo implements support for it. Am I missing something?
The state of debugging jsoo in the browser is actually excellent.
Sys is a system API, it’s irrelevant to the discussion. It was indeed already the case for Weak but 1) luckily it is rarely used 2) it was still implemented albeit with a strong semantic which turned out not be so much of a problem for wepages.
Not supporting effects becomes a problem if people start using them heavily in libraries, possibly only internally. I hope this does not happen. Personally the reason why I always wanted to have effects in the mainline is precisely so that I don’t need to use them… But it may take some time for people to realize that effects are still side effects :–)
The state of debugging jsoo in the browser is actually excellent.
Do you mean debugging jsoo programs using sourcemaps? That cannot be as convenient as debugging transpiled Rescript javascript which is quite readable and lightweight (and does not need sourcemaps to debug). I was trying to be comparative here. Sourcemaps in general are bulky, the browser is janky during debugging anyways – add potentially multiple MBs of sourcemaps and I can’t imagine how that would be a user friendly experience.
If you’re talking about debugging using the OCaml top level in JSOO, again that’s using something that running on the OCaml runtime which is being emulated on the JavaScript runtime. An extra level of indirection is not always convenient.
Lastly, you are the author of brr – a nice library built on jsoo – your skills are likely to be much better than the average person who wants to target the browser using OCaml!
I think most people will be very understanding of a policy ~“multicore/parallel domain capabilities cannot be used when targeting javascript”. That is typical among various compile-to-js projects.
Effects are a fundamental language feature though (and not “just” a runtime capability), so trying to carve them out as part of defining what is javascript-safe would be a significant loss.
Even if tomorrow an actual wasm backend existed, and interop/FFI questions were settled, wasm would continue to be a challenging deployment target, viz. Wasm needs a better memory management story · Issue #1397 · WebAssembly/design · GitHub. As much as I appreciate the wasm vision and that it will likely eventually-someday actualize some large part of the hopes and expectations people heap on it, it doesn’t seem like anyone should planning on it rather than existing compile-to-JS options.
To reiterate what I understood as @avsm’s point (which I agree with), we do not want OCaml to stagnate due to the limitations of a particular platform. Effects are not just some ‘nice to have’ features. Once we get proper typed effects in the language (i.e. not OCaml 5.0 but further down the line), we’re talking about a paradigm shift in the capabilities and safety of the language. We want to get there. If JSOO compilation is becoming more challenging because the language as a whole is advancing, then that’s all the more reason to meet the challenge on the JSOO side.
@kayceesrk is there a link to your presentation about implementing effects in js? The paper you linked earlier looks very interesting, but I couldn’t find any more detail
I think there are really two issues that are coming up here: the first is a immediate-term question about what features are supported for OCaml 5.0; and the second is what the medium-term plan for jsoo is after that.
About the immediate, OCaml 5.0 question, the current plan for multicore is ambitious, and I’m glad the team made choices of some things to not do, to make the whole thing possible. This includes dropping support for families of CPUs, and adding effects before we have a good type-level discipline or syntax for handling them. And it includes not settling the JavaScript story.
I think these are largely very good choices, and I’m glad the core team has put together an aggressive and focused plan to get multicore out the door.
That leaves the question of what should be done about effects and js_of_ocaml after OCaml 5.0. I suspect there’s more agreement here than it seems at first. Some statements I suspect aren’t too controversial:
Wasm getting to the point that we can drop jsoo is plausible, but likely years away. We can’t rely on it.
Having effects simply be unsupported in jsoo will over time significantly degrade the experience of coding for the browser in OCaml, because effects are likely to be useful and relatively common, even in code that isn’t using parallelism itself.
But, use of effects in OCaml 5.0 is intended to be fairly small. It’s there to help develop the system and allow for experimentation, but it’s not intended as something to be used routinely.
All of which is to say: jsoo support for effects is something we’re going to need to do, much as we’re going to need to bring back support for the various CPUs that are planned for removal in the first version. But I don’t think it’s critical for OCaml 5.0.
I think this discussion has lit a bit of a fire under those of us who depend on jsoo (which most certainly includes Jane Street) to do what we can to make sure that support for effects in jsoo happens sooner rather than later, which I think is a good outcome! The team working on multicore is small, and they’ll need all the help they can get.
Compilation of effect handlers to JavaScript is an interesting problem (more generally, compilation of any first-class continuation-y thing is interesting). As KC mentioned earlier, in the past collaborators and myself investigated various compilation strategies for effect handlers to JavaScript. The strategies we investigated were: (selective) CPS, free monads, encoding as generators/iterators, abstract machine (~ interpreter), exceptions+state, I gave a presentation about this work at ProWeb in 2018 (you can find the slides on my website https://dhil.net/research/talks/proweb2018-04_handlers-js.pdf).
The preliminary results show that CPS performs best. My hypothesis for why that is so, is that JavaScript VMs have spent years optimising for the “callback hell”. It is important to note that those results are for “continuation heavy code”, i.e. code which captures and invokes the continuation often. The picture may well be different for code that does not make use of the continuation facilities.
It is also worth noting, that the CPS translation that I implemented was for effect handlers with multi-shot continuations, in the case of Multicore OCaml, where continuations are single-shot, you may be able to get even better performance using a linear CPS translation – I think this is an approach worth investigating.