[m-users.] When is nondeterminism appropriate?

Philip White philip at pswhite.org
Wed Feb 17 12:25:26 AEDT 2021

On Tue, 16 Feb 2021 14:15:07 +0100
Volker Wysk <post at volker-wysk.de> wrote:

> Am Dienstag, den 16.02.2021, 14:09 +1100 schrieb Zoltan Somogyi:
> > 2021-02-15 23:40 GMT+11:00 "Volker Wysk" <post at volker-wysk.de>:  
> > > Am Sonntag, den 14.02.2021, 15:32 -0500 schrieb Philip White:  
> > > > :- type result ---> ok(T) ; error(string).
> > > > 
> > > > "functions that can fail" (either because of user error or
> > > > something else) seems like the perfect time to use semidet, but
> > > > if I want to have good error messages, then semidet will not
> > > > help me, and I might as well try to make my function
> > > > deterministic.  
> > > 
> > > This might be a good opportunity for using exceptions.  
> > 
> > One difference between those two approaches is that returning
> > an error indication explicitly makes it significantly easier to
> > return *more than one* error indication.
> > 
> > Consider the code in the Mercury compiler that parses a pragma
> > that has several arguments (e.g. foreign_proc pragmas). It is
> > possible for each argument to have one or more syntax errors inside
> > it. We want the parser to print an error message for *each* syntax
> > error, to allow programmers to fix N syntax error errors with one
> > recompilation, instead of N recompilations.
> > 
> > The compiler uses a variant of the approach described by Philip,
> > with the difference being that the error case describes not one
> > error, but one or more errors. The code for parsing e.g. a
> > foreign_proc pragma then just parses each argument, and then checks
> > whether they all returned ok(...). If yes, it constructs the
> > representation of the pragma from the arguments inside those ok()s,
> > and wraps an ok() around it. If not, it appends error lists inside
> > the error()s, and wraps another error() around the result. This
> > code is simple and direct. I don't think I would say the same of
> > code that tried to do this with exceptions.  
> In this case, when you want to aggregate the errors/error messages,
> this might be the best way to do it.

As a matter of fact, I am aggregating several errors, even though my
original email didn't demonstrate that.

> But in Philip's case, I think exceptions would handle it more
> elegantly. You'd have less clutter, and his functions/predicates
> could be deterministic. And you'd jump to the appropriate catch
> handler, unwinding the stack, and have even less clutter. It's what
> exceptions are there for.

In my opinion, exceptions are for handling programmer error - in a
bug-free program, an exception should never be thrown. Although we may
say that bad user input is invalid, I think programs should treat bad
user input at the same level as good input. Perhaps that is just a
matter of programming taste. Using exceptions just to make a
predicate/function deterministic a little disingenuous. You can make
any semidet predicate into a det one by throwing an exception if the
predicate has no solutions.

More information about the users mailing list