Small poll

Joachim Durchholz joachim.durchholz@REDACTED
Wed Dec 17 10:26:42 CET 2003

Richard A. O'Keefe wrote:
> The C equivalent of (SHOULDNT) is abort().  Not, by the way, assert(0).

If that's the case, SHOULDNT shouldn't be in the language.
After all, forcing the execution of the program to a halt is unmodular: 
the caller might want to run the code and try an alternate strategy. 
(Heck, that's what Erlang is all about: surviving faulty code that does 
thing's that shouldn't happen.)

 > Is it clear to everyone that
 >     "This code must raise an exception at run time"
 > and
 >     "This code is in error"
 > are different?

This classification isn't complete, and I think the ongoing discussion 
is at least partially senseless because wrong distinctions of this kind 
are constantly being made.
Actually, Erlang has more failure modes (and this list may not even be 
1. Erroneous code that's rejected by the compiler. This includes stuff 
like "1 = 2 3".
2. Code that will raise an exception. Example: "1 = 2".
3. Code that will terminate the process. Essentially, that's code that 
doesn't catch all exceptions that may occur.
4. Code that will terminate the Erlang node.
5. Code that will terminate all communicating Erlang nodes.

Category 2 is what most confusion comes from: depending personal 
definitions, one may consider it erroneous or not (and either definition 
makes sense, depending on the point of view).

There's another source of confusion: Some people here argue that a 
compiler shouldn't change the semantics of the language, but is that 
indeed the case? Both syntax and semantics of Erlang have changed over 
the years, in in an upwards-compatible fashion.

> Is it also clear that
>     "This code is obviously silly"
> and
>     "This code must raise an exception at run time"
> are different?  Lint warns about things that are clearly silly,
> yet perfectly legal, and perfectly harmless.  For example,
>     x == y;
> as a C statement is perfectly well defined, and quite harmless,
> yet lint warns about it because you probably didn't mean it.
> A C compiler which refused to compile such a program would not
> be helpful, it would be buggy.

A C compiler would emit a warning and be compliant.

If I were to decide, I'd adopt a similar policy: issue warnings about 
constructs like 1=2.

However, I dislike somethine entirely different about them. There's 
clearly a need to make a computation fail, and different people use 
different idioms to express is. Some say 1=2, others say a+0, and I saw 
mentions a handful others.
While that's neat, it's also an unnecessary maintenance obstacle. 
Whenever a maintainer sees such code, he has to (a) find out what this 
code does (which will take more time than usual because he'll have to 
revisit the usual assumption that code isn't written for raising 
exception), (b) figure out whether the code is raising the exception 
intentionally or not.
There are two additional disadvantages: (c) it's impossible to do a grep 
to see whether any temporary exception-raisers were accidentally left in 
some code that's considered ready for production release, and (d) if the 
code does raise an exception, it will give the maintainer wrong 
information: the true error is that the system is trying to execute 
unwritten code, but the system will give a different error message.

I'm quite mystified why there isn't a "niy" (not implemented yet) or 
"tbd" (to be determined) routine, that explicitly raises an exception 
saying "fatal error: trying to execute code that has not yet been 
written" (or something similar).

Once such a routine is in place, the question whether changing the 
semantics of obviously silly constructs is a no-brainer: if there's no 
useful purpose for them, their semantics is irrelevant and can be 
changed. One may adopt a more conservative approach and maintain 
compatibility with legacy code, so a warning would probably be more 
appropriate. An even better option would be if that warning could be 
turned into an error for those shops who want strict discipline (not all 
shops need that, but sometimes there are good reasons to turn on the 
equivalent of -Wall --warnings-as-errors).

> It is possible to make (=)-for-(==) and (==)-for-(=) errors in
> Erlang, and lint checking for Erlang might warn about them even
> though they are legal.
> Whether a particular piece of apparent silliness is worth warning
> about is an empirical question:  how often do programmers make the
> kind of mistake that results in an instance of that pattern, and
> how often do they intend it?

And, more importantly: how easy is it to make the compiler detect that 
pattern, and how likely is it that the compiler will make errors when 
identifying such patterns?

> I've worked on a couple of compilers for languages that supported
> exception handling.  (I _think_ mine was the first paper on doing this
> for Prolog, except that Quintus insisted on yanking it from the conference
> after it was accepted.)  Exception handling can be very tricky to get
> right.  (There's a debate raging in the Clean mailing list at this moment.)
> ANSI Smalltalk exception handling is a case in point; to me it seems
> insanely complicated, and it's not clear that Squeak has got it 100% right
> yet.  This means that especially when you are maintaining compilers, you
> _need_ simple test cases which are certain to cause exceptions because
> that's what you're testing.

There's always the explicit exception raising statement. Any language 
that has exceptions should have such a statement, and Erlang does it right.

Actually, I don't think that generating a test case should be a problem, 
ever. There's always the possibility to do unit testing. You'll have to 
structure the compiler so that it has units to be tested, but this 
restructuring will clean up the compiler considerably, making is more 
stable and reliable, so this is a good idea anyway. Loss of test cases 
due to changes in language syntax or semantics is just an indicator that 
the compiler is badly structured IMNSHO.


More information about the erlang-questions mailing list