4 ms·
The Ocaml exception implementation is comparatively very performant, and so its exceptions are routinely used for control flow.
by momentoftop 7y ago
The Ocaml exception implementation is comparatively very performant, and so its exceptions are routinely used for control flow.
- Rapzid 7y agoInterestingly .Net has very performant exception handling as well. Not sure if something changed internally with Core, but using exceptions in place of return error codes was incredibly common within the .Net ecosystem.
- profquail 7y ago.NET has always had slow exception handling because it tied/ties in Windows’ Structured Exception Handling (SEH); that’s rather slow but provides e.g. detailed stack traces even for mixed-mode callstacks. Having ported some decently large codebases from OCaml to F#, the heavy use of exceptions in OCaml (where exceptions are very lightweight by design) had to be changed to normal control flow with monads to achieve good performance in F# — specifically because of .NET’s slow exception handling.
- 9q9 7y agoI'd be interested to learn about how exceptions are typically using in Ocaml for non-local control flow. Exceptions have two core properties: (1) non-local jump (carrying a value) and (2) dynamic binding of place to jump to. Contrast this with e.g. break / continue in loops where (2) does not hold. If most use cases of performant OCaml exceptions were not making use of (2) that would be an interesting insight for programming language design. Have you got data on this matter?
- momentoftop 7y agoNo data as such. But here's the first example in the "batteries included" list library: let modify_opt a f l = let rec aux p = function | [] -> (match f None with | None -> raise Exit | Some v -> rev ((a,v)::p)) | (a',b)::t when a' = a -> (match f (Some b) with | None -> rev_append p t | Some b' -> rev_append ((a,b')::p) t) | p'::t -> aux (p'::p) t in try aux [] l with Exit -> l Here, the Exit exception is being raised as an optimisation: if no modification happens, then we return the original list, saving an unnecessary reverse. The try is the only place that the Exit exception is caught, so the jump location is static, much like a break.
- 9q9 7y agoThanks. That's, as you say, a statically scoped fast exit. One does not need the full power of exceptions for this (exceptions'd dynamic binding comes with a cost). If exceptions are widely used for this purpose, one might consider adding a nicely structured goto to the language. Something like linear delimited continuations?
- momentoftop 7y agoSorry, I misunderstood what you were after. Ocaml exceptions are used more generally, and often make use of 2. For instance, the basic stream/iterator in Ocaml is Enum, which always uses an exception to signal when the stream has been exhausted, rather than providing a "has_next" predicate. The catch site of this exception is dynamic.
- 9q9 7y agoThat is interesting. Once could argue that since fast exceptions contain non-local jumps with a static target, it is enough to supply only the former, so as to simplify the language.