DISQUS

Skydeck Blog: Stack traces in OCaml

  • igor · 2 years ago
    external capture_backtrace : bool -> unit = "caml_capture_backtrace";;
    external sprint_backtrace : string -> int = "caml_sprint_backtrace";;

    Have this lines to be commented (in the path) and uncommented (in the step 7)?
  • Jake · 2 years ago
    No, those lines (in stdlib/printexc.ml) do not need to be commented/uncommented; since those functions are not used and don't appear in printexc.mli, they are not added to the table of required primitives, so there is no problem linking with the bootstrap ocamlc.

    Did this not work for you?
  • igor · 2 years ago
    sorry, it was my mistake.
    it works =)

    this patch is hard enough to be included into the ocaml deb-package...
  • Jake · 2 years ago
    Cool.

    If you want to create a source tarball that incorporates the patch, do steps 1-6, which will build ocamlc, ocamldep, and ocamllex in boot/. Save these somewhere. Now do steps 1-3 again, copy the new ocamlc, ocamldep, and ocamllex into boot/, then do step 7. The resulting directory may be built in the standard way (make world etc.), so you can tar it up.

    I didn't do this for the patch release because I didn't want to redistribute the whole system or a binary patch.

    (You may not need ocamldep and ocamllex; I think it is only ocamlc that actually checks the primitives, but you might as well include them for uniformity.)
  • seanmcl · 2 weeks ago
    "this reflects a design choice to make exceptions very lightweight. Because exceptions are cheap it is good OCaml style to use them freely as a control-flow mechanism, while in most other languages such use is discouraged—exceptions are meant to be used only for error handling."

    Does Skydeck use exceptions a great deal for control flow? I'm curious, because I'm translating some Ocaml code to Haskell that uses exceptions in this way. Of course, in Haskell the exceptions must either be translated into pure functions (Maybe/option), or everything would need to live in the IO monad. I chose to keep things pure, so I can not translate the code directly. Attempting to determine which functions should return options is not always, or even often, obvious. Since exceptions are not in the types, it is very difficult to determine what functions are raising exceptions when the control flow is not explained some way or another (e.g. in comments).

    While in my SML and Ocaml code I used to use value-carrying exceptions a great deal as control mechanisms, after this experience I think I will refrain from doing so.
    In my opinion, as a reader it is much more difficult to understand exceptions than Maybes.
  • jaked · 2 weeks ago
    Hi Sean,

    I agree that it is hard to understand what exceptions may be raised by a function, since that is not captured in the type. (On the other hand my experience with checked exceptions in Java is that they hinder modularity; I think this is because there is no polymorphism over exceptions.)

    Using options or a result type directly is pretty painful; the monadic approach seems better to me. You might be interested in this paper, which implements exceptions handling in OCaml with an error monad (using polymorphic variants to structure exceptions) and explores how to recover the performance of native exceptions:

    http://www.univ-orleans.fr/lifo/Members/David.T...

    To answer your original question, we do use them a fair amount for control flow. But I think the situation is a bit like with references: global references can make code hard to understand, but the local use of references in code (that presents a pure interface to its callers) is OK. The same goes for exceptions; local use of exceptions can clarify code, but their global use (for control flow at least; error handling is a separate matter) can be confusing.
  • seanmcl · 2 weeks ago
    Hi Jake,

    I agree the monad is an improvement. I was indeed using Maybe as a monad to avoid the explicit cases everywhere. Perhaps an error monad is really what you want in more complex cases. One nice thing about Haskell is that you can write your code over an arbitrary error monad and then change the errors around without changing the code very much. For instance, you can posit a monad dealing with errors as

    class Monad m =>MonadError m where
    ...

    and then write

    MonadError m => f :: Int -> m Int
    f 0 = fail
    f n = return $ n + n

    then you can plug in Maybe, or Either Int Error, or some other error type when you figure out what you actually want.

    The polymorphic variants is a nice touch in Ocaml.

    Thanks for the response.

    Best,

    Sean