4.6 KiB
Exceptions handling
Exceptions are widely used in modern programming languages, so they are implemented also in Lyng and in the most complete way.
Exception classes
Exceptions are throwing instances of some class that inherits Exception
across the code. Below is the list of built-in exceptions. Note that
only objects that inherit Exception
can be thrown. For example:
assert( IllegalArgumentException() is Exception)
>>> void
Try statement: catching exceptions
There general pattern is:
try_statement = try_clause, [catch_clause, ...], [finally_clause]
try_clause = "try", "{", statements, "}"
catch_clause = "catch", [(full_catch | shorter_catch)], "{", statements "}"
full_catch = "(", catch_var, ":", exception_class [, excetpion_class...], ")
shorter_catch = "(", catch_var, ")"
finally_clause = "{", statements, "}"
Let's in details.
Full catch block:
val result = try {
throw IllegalArgumentException("the test")
}
catch( x: IndexOutOfBoundsException, IllegalArgumentException) {
x.message
}
catch(x: Exception) {
"bad"
}
assertEquals(result, "the test")
>>> void
Because our exception is listed in a first catch block, it is processed there.
The full form allow a single catch block to process exceptions with specified classes and bind actual caught object to the given variable. This is most common and well known form, implemented like this or similar in many other languages, like Kotlin, Java or C++.
Shorter form
When you want to catch all the exceptions, you should write catch(e: Exception)
,
but it is somewhat redundant, so there is simpler variant:
val sample2 = try {
throw IllegalArgumentException("sample 2")
}
catch(x) {
x.message
}
assertEquals( sample2, "sample 2" )
>>> void
But well most likely you will find default variable it
, like in Kotlin, more than enough
to catch all exceptions to, then you can write it even shorter:
val sample2 = try {
throw IllegalArgumentException("sample 3")
}
catch {
it.message
}
assertEquals( sample2, "sample 3" )
>>> void
You can even check the type of the it
and create more convenient and sophisticated processing logic. Such approach is
used, for example, in Scala.
finally block
If finally
block present, it will be executed after body (until first exception)
and catch block, if any will match. finally statement is executed even if the
exception will be thrown and not caught locally. It does not alter try/catch block result:
try {
}
finally {
println("called finally")
}
>>> called finally
>>> void
- and yes, there could be try-finally block, no catching, but perform some guaranteed cleanup.
Conveying data with exceptions
The simplest way is to provide exception string and Exception
class:
try {
throw Exception("this is my exception")
}
catch {
it.message
}
>>> "this is my exception"
This way, in turn, can also be shortened, as it is overly popular:
try {
throw "this is my exception"
}
catch {
it.message
}
>>> "this is my exception"
The trick, though, works with strings only, and always provide Exception
instances, which is good for debugging but
most often not enough.
Custom error classes
this functionality is not yet released
Standard exception classes
class | notes |
---|---|
Exception | root of al throwable objects |
NullReferenceException | |
AssertionFailedException | |
ClassCastException | |
IndexOutOfBoundsException | |
IllegalArgumentException | |
IllegalAssignmentException | assigning to val, etc. |
SymbolNotDefinedException | |
IterationEndException | attempt to read iterator past end, hasNext == false |
AccessException | attempt to access private members or like |
UnknownException | unexpected kotlin exception caught |