Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm a big fan of Lua and Go's use of multiple return values, nil, and simplified error handling, (No exception 'types'). I think the problem with 'typing' Exceptions is that it means you are using it to record and pass describable\known state similar to return, instead of being reserved for unknown state. For indicating predictable failure states without using exceptions, I think multiple return values as used in Go and Lua is a much better paradigm. To recap Steve's post, opening a non-existent file in Lua:

    =io.open 'sdfasdf'
    nil	sdfasdf: No such file or directory	2
The first value returned is nil, the 2nd value is a string containing an error message, and the 3rd is an integer error code. This allows you to write most code using 2 state boolean logic:

    f=io.open 'sasdasdfsf'
    if f then -- nil is a boolean 0
whereas in Python, one often has to reason about 3 states due to the use of try\except blocks. Even though you are not using typed Exceptions, multiple return values does not discard any state about the error if it is desired:

    f, err = io.open 'sasdasd'
    print(err)
In Lua (not Go), when you combine multiple return values with an assert() function of the form assert(boolean, error_message), you effectively get a mechanism for making exceptions optional:

    > =assert(io.open 'sdfasdf')
    stdin:1: sdfasdf: No such file or directory
    stack traceback:
    	[C]: in function 'assert'
    	stdin:1: in main chunk
    	[C]: ?
Although Go does not appear to include assertions at all, arguing against them in its FAQ: http://golang.org/doc/go_faq.html#assertions


The idea of exceptions is not primarily reading out details from the throw exception object, but to let programmers code the "happy flow" as if errors can not happen. It also makes it easier to let callers further up in the call-chain to set the policy of of what to do in case of an error.


And then, if you go one step further to conditions (Smalltalk, Common Lisp) callers can even setup a recovery policy for the error without unwinding the stack.

Smalltalk systems use this to great success to allow for e.g. dropping straight into the debugger at an error point (without any loss of context) even when the system is not technically being debugged.


I had Common Lisp Conditions in mind when I wrote my message above. Have an upvote for knowing stuff. :)


> The idea of exceptions is not primarily reading out details from the throw exception object, but to let programmers code the "happy flow" as if errors can not happen.

The problem is that errors can and will happen, and exceptions make the control flow of error handle unpredictably convoluted.

From a control flow point of view exceptions are worse than COMEFROM.

> It also makes it easier to let callers further up in the call-chain to set the policy of of what to do in case of an error.

Callers that do not have any of the real context in which the error happened, and that often can't do anything particularly smart about it other than throw their hands in the air.


Thanks for mentioning

http://en.wikipedia.org/wiki/COMEFROM

A joke in 1973 -- kind of a reality with the exceptions. As early as FORTRAN IV, IO operations errors were handled in higher level programming languages:

  WRITE( 6, 30, ERR=390 ) 
specified that error handling for that given write operation was behind the label 390.

The march of progress, just like even the first FORTRAN circa 1956 did

     WRITE (6, 150) X
 150 FORMAT (F10.2)
But C++ since 1988 improved it with

  cout << setw(10) << setprecision(2) << showpoint << x;
or Java 1996 with:

    java.text.NumberFormat formatter = 
         java.text.NumberFormat.getNumberInstance(); 
    formatter.setMinimumFractionDigits(2); 
    formatter.setMaximumFractionDigits(2); 
    String s = formatter.format(x); 
    for (int i = s.length(); i < 10; i++) 
         System.out.print(' '); 
    System.out.print(s);
The march of progress.


> The problem is that errors can and will happen, and exceptions make the control flow of error handle unpredictably convoluted.

I take it you never have seen the "leaning Eiffel tower of nested if's in C/Pro-C? As I wrote, in a language with exception handling you code as if errors never would happen. And then you put using/try+finally/block-exit clauses around your statements to assure cleanup will happen no matter what.

How is that convoluted? Good such code looks almost naïve to me.

>Callers that do not have any of the real context in which the error happened, and that often can't do anything particularly smart about it other than throw their hands in the air.

Well, exactly how smart a caller can be is decided by the protocol between caller and callee. It's no different than what return-values would have given you IMHO.


IMO going back to return statements for error detection is to throw away years of advancement. The problem with what you're describing is now every call has to be tested for errors because only the call-site has a chance to do this.

Contrast this with exceptions: if I don't know what to do with a failure at this level then I just ignore it. Some caller higher up the chain will know and can handle it.

Your examples seem overly trivial. In real code it would be very rare for the level of code that's actually opening files (something far down in the libraries) to also be handling exceptions.


Go actually does provide a mechanism similar to exceptions. The functionality is provided by the functions panic, defer, and recover. Idiomatic Go does not like panics (i.e. exceptions) to escape API boundaries, but otherwise you are just as free to use them as any language providing exceptions.


Years of advancement or years of wandering aimlessly? It depends on the coders, of course. More often than not I've seen exceptions used for non-exceptional errors: normal errors best handled immediately by the code that triggered it. The use of exceptions there needlessly defers dealing with the error, passing it up the call chain to code that shouldn't know particulars.

Making both returned errors and exceptions available at least offers the opportunity to use the better tool for the circumstances. Both are very valuable and clear under different circumstances.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: