3
$\begingroup$

I'm working on a new general-purpose programming language. Exception handling is supposed to be like in Rust, but simpler. I'm specially interested in feedback for exception handling (throw, catch).

Questions:

  • The catch catches all exceptions that were thrown within the scope. I argue there is no need for try, because try would requires (unnecessary, in my view) indentation, and messes up diffs. I wonder if other programming languages have this feature? I didn't find any. Is there a problem with this idea?

  • I think one exception type is sufficient. It has the fields code (int), message (string), and optional data (payload - byte array). Do you see any obvious problem with this?

Exceptions

throw throws an exception. catch is needed, or the method needs throws. In the following example, the scope of the catch is the while loop.

fun factorial(x int) int throws
    if x > 20
        throw exception('Value too large')
    if x <= 1
        return 1
    f := factorial(x - 1)
  return x * f

fun main()
    i := 0
    while i <= 30
        println('Factorial of ' i ' is ' factorial(i))
        catch e
            println('Factorial of ' i ' resulted in ' e.message)
        i += 1
$\endgroup$
12
  • 1
    $\begingroup$ If there is a scope, why doesn't it have indentation? $\endgroup$
    – Bergi
    Commented Jun 27 at 2:25
  • 3
    $\begingroup$ BTW, are you aware of the Programming Language Design and Implementation Stack Exchange? $\endgroup$ Commented Jun 27 at 8:32
  • $\begingroup$ @JörgWMittag oh, I was not! Thanks a lot! I will ask the question there! $\endgroup$ Commented Jun 27 at 9:00
  • $\begingroup$ What is e? Unless your language is structured in a way that prevents it, it looks like e could have come from multiple locations: (square(), println(), before those, deeper inside square, when passing a non-int into square, etc) $\endgroup$
    – Mars
    Commented Jun 27 at 9:10
  • $\begingroup$ e is a variable name that contains the exception. Yes the exception could come from multiple locations (same as in other programming languages that have a try ... catch block). I think that is good: I wouldn't want that the programmer has to handle possible exceptions for each and every method call (as in C or Go). That is the point of using "catch". But unlike Java, in my language, each of the methods that can throw an exception needs to declare it. So my language is similar to Swift, in this regard. $\endgroup$ Commented Jun 27 at 9:13

2 Answers 2

4
$\begingroup$

In Ruby, an exception handling block looks like this:

begin
  # something which might raise an exception
rescue SomeExceptionClass => some_variable
  # code that deals with some exception
rescue SomeOtherException => some_other_variable
  # code that deals with some other exception
rescue YetAnotherException
  # code that deals with yet another exception and does not capture it
rescue
  # code that deals with any sub-exception of `StandardError`
else
  # code that runs only if *no* exception was raised
ensure
  # ensure that this code always runs, no matter what
  # does not change the final value of the block
end

Most of the clauses are optional.

There are some language constructs which form implicit exception blocks, namely method definition bodies and block bodies. So, instead of

def foo
  begin
    # something which might raise an exception
  rescue SomeExceptionClass => some_variable
    # code that deals with some exception
  rescue SomeOtherException => some_other_variable
    # code that deals with some other exception
  rescue YetAnotherException
    # code that deals with yet another exception and does not capture it
  rescue
    # code that deals with any sub-exception of `StandardError`
  else
    # code that runs only if *no* exception was raised
  ensure
    # ensure that this code always runs, no matter what
    # does not change the final value of the block
  end
end

you can also write

def foo
  # something which might raise an exception
rescue SomeExceptionClass => some_variable
  # code that deals with some exception
rescue SomeOtherException => some_other_variable
  # code that deals with some other exception
rescue YetAnotherException
  # code that deals with yet another exception and does not capture it
rescue
  # code that deals with any sub-exception of `StandardError`
else
  # code that runs only if *no* exception was raised
ensure
  # ensure that this code always runs, no matter what
  # does not change the final value of the block
end

And the same for blocks.

$\endgroup$
2
  • $\begingroup$ Thanks a lot! I struggled quite a lot finding other languages that support this type of syntax. I was (almost) sure that there was at least one popular language, as omitting "try" (well, "begin", in this case) seems obvious to me. $\endgroup$ Commented Jun 26 at 19:28
  • 1
    $\begingroup$ Since the question mentioned indentation, it's worth noting that this structure does not match the example in the question - the catch (or rescue) block is not inline in the block. It's more like the def keyword is simultaneously acting as the try. $\endgroup$
    – IMSoP
    Commented Jun 27 at 14:24
2
$\begingroup$

You are losing a lot.

For example, in Swift a non-throwing function isnt allowed by the compiler to call a throwing function outside a try block - which means that I, as the developer, know definitely that no code outside the “catch” can throw exceptions, guaranteed by the compiler. And if you call any code that could throw exceptions after the last catch ghen you must report an error. Now what if the catch statement is inside an if?

Functions don’t catch exceptions all over the place. Exceptions are exceptional. You have functions that do nothing that can throw exceptions, and then enter one area where exceptions can happen. I want to handle exceptions in that area - and be sure there are no exceptions elsewhere. So my “catch” code knows which exceptions should arrive and which shouldn’t.

$\endgroup$
3
  • $\begingroup$ > "in Swift a non-throwing function isnt allowed by the compiler to call a throwing function outside a try block" ... except if the function throws itself. Which I think is the right choice! (Same as in Rust). $\endgroup$ Commented Jun 27 at 8:53
  • $\begingroup$ > Now what if the catch statement is inside an if? Then the catch statement will only catch exceptions that are thrown within the if statement. $\endgroup$ Commented Jun 27 at 8:55
  • $\begingroup$ When I read you comment (answer?) I think that you might have misunderstood my proposal. I'm planning to have the same type of exception handling as Swift, which is "catch is needed, or the method needs throws". Same as Swift. $\endgroup$ Commented Jun 27 at 8:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.