Perhaps we’re debating the difference between the way things ought to be, and the way they are. You’re arguing that a particular way of writing code can produce better code, that doesn’t need stack tracebacks to debug; I’m arguing that there’s too much code out in the world that doesn’t conform to that discipline, and that if OCaml is going to make the kind of inroads into the Great Unwashed Masses that many people here desire, then that latter kind of code will vastly predominate.
I mean, test-driven development is great stuff! I got to live that experience, so it’s not a theoretical fancy to me: I -recognize- the value of that methodology for building systems. Notwithstanding, it’s clear that lots of people practice it in name only. At best.
It’s not an either-or situation, though. I write my APIs in this style I’m proposing, and document no exceptions are thrown, and you get the benefits on my APIs, and in cases where I cannot control it I even do pull the backtrace out for the user and pack it into my error code, because I live in the real world and that’s what one has to do. But you can asymptotically approach what I’m describing, it’s not necessary to reimplement the world.
@Chet_Murthy goes off thread ! The question is asked by an Ocaml user to other Ocaml users within our Ocaml community on a discuss.ocaml.org forum. Not only it has the inherent academic semantic to it, but also it has the learning tag attached to be explicitly redundant. He refers to his track of past jobs with outsiders, who write code in other languages, designed with poor alien habits I can’t think of.
Counter example to " the community wants , thinks, does this or that " :
I, milvi, consume and produce, read and write Ocaml for my Ocaml peers, and binaries to the world.
It’s not like Ocaml is a de facto standard in the open. Hence, I surmise everyone chose to come here because they have the gift of mathematics/came because they understand / like / are drawn to it.
About Ocaml everywhere everyone mention : If you have to sell yourself doing consulting for, not the real world, but the outside world, avoid the common following mistake. Every brain is machine/language/interpreter. If they write in imperative and not functional it’s because there are that. No one changes. If you trade with others (society is a disjoint union of communities), don’t go on crusades pushing with brute force your brain language in their different brains. This is madness. Just make your tooling with your language and debug/make a binary with it (opaquely encapsulated away from your client). Let them be whoever they are in their code. We are as many as the distribution of our braingraphy. Why want “more” “more” “more” people ? Expansion ? Convert the “others” ? Ain’t we all equivalent here in a way ? So is it the want for raw brain power to count more than that of the outsiders ? I don’t get it, whether that was ever an objective. I just get publicity and accessibility for next vocations. Growing the community amounts to take in Haskell/Scala/ML users.
@Chet_Murthy Like I would ever include not_Ocaml code in my beautiful Ocaml ! I just don’t understand at all why you keep bringing up irrelevant practices and customs from outsiders. It’s called Ocaml forum, Ocaml repositories, Ocaml libraries, Ocamlverse ! Comparative study is cool. But you are pitching inter ethnic ways and saying " if you share/use code made by alien programmers then go for the common denominator to deal(absorb) their poor discipline"… Hum, wait, no, never heard of the likes of them, I(one) associate(s) with my(his) equals. They are all here, struck by monadic arrows.
Joris at Ahrefs wrote something inspired by the error handling in rust. It’s not fully polished. But it might be interesting to look at. One benefit is a clear delimitation between errors that are meant to be handled internally and the ones for the outer world.
Yeah, I remember some lengthy discussions on error handling in the Haskell scene, where some parties were determined to make a semantic distinction between two different kinds of error cases. At the very great risk of misrepresenting the discussion, I think the attitude was more or less that a truly correct program would never raise any exception, because it would have accounted for all possible inputs, and in this sense they reserved exceptions as a mechanism for expressing program incorrectness.
Haskell is of course in a very different situation in this matter, because of the unusual evaluation/exception model. Also, contributing to the irrelevance of this observation, I’m essentially speaking to the question of exceptions vs. error returns in general and ignoring the traceback issue that seems to be of primary interest here.
It’s an interesting phenomenon in itself how hard it is to reach consensus in such a fundamental matter. Hm. Maybe a third or forth way will pop up some day to convince both camps? A la Hegel.
I apologize for resurrecting this thread. I wonder, if there is any tool or script that allows to fish out all functions in the code that can throw exceptions and just make a list of those, so that they can be converted into something more deterministic?
I consider those “panics” and I think exceptions work well for that. I would define a panic as giving up with the current operation and not trying to recover, except perhaps at a much higher level (e.g., a web container would continue processing other requests if my request handler threw a Failure exception).
failwith and invalid_arg are guaranteed to raise exceptions. assert false can potentially raise, so it should be marked with an alert (if we are following the alert approach).
As someone who has written such analyses, I would say that you are not providing a precise enough specification.
If you want to know all the functions that, in some context, may exit through an exception instead of a normal return, then you can just make a list of all functions (there are very few pieces of code that are guaranteed to never throw any exceptions).
If you want to know all functions that may raise an exception from OCaml code directly, then it is possible but being precise is going to be a lot of work (François Pessaux spent his whole PhD doing that, to make it cover the whole language at the time would have taken even longer, and maintaining it would be more than one can do in one’s free time). And you still have to decide whether you want to consider things like out-of-bounds array accesses or assert failures (normal exceptions that have no corresponding raise call) as problematic or not.
In the end, grep raise may be the best compromise for you: not precise, but it is still going to find at least a few problematic cases at very little cost.
If you are able to give a more precise specification, I could also estimate how much time it would take me to implement it.
Using grep is not enough unless you consider the code of all libraries, too. I would suggest to disassemble the binary and grep through it. I agree with your general direction: properties like these are difficult to get right unless the language (and its type system) are designed to track them, which OCaml is not. The new work on effect systems offers a chance to change it.
I read all your comments and I totally agree with you.
I use ('success, 'error) result or even a dedicated sum type (e.g. when a function has 3 possible kinds of results) for function return type. For code paths that should NEVER happen, let it crash by assert false.
Furthermore, here’s an observation: the more powerful a language’s type system is, the less you need to assert for defensive programming —
With a dynamically typed language (e.g. Scheme), you may need to assert the input is a number, e.g., (number? x);
With a statically typed language without dependent types (e.g. OCaml), you don’t need the kind of assertions above. However, you may need to assert the length of the input array;
With a dependently typed language (e.g. Idris), you don’t need to assert the length of the input array, because you encode it inside the type of the input array!
Essentially, the more powerful a type system is, the more errors it rules out from the beginning.
I remember reading somewhere that Jane Street used to prefer result, but is now preferring exceptions because OCaml is expected to get typed exceptions or effects? However, I tried to search up this claim and can’t find it anywhere. Am I just making this up?