aboutsummaryrefslogtreecommitdiff
path: root/docs/ERRORS.md
diff options
context:
space:
mode:
authorJJ2024-01-28 09:05:03 +0000
committerJJ2024-01-28 09:07:00 +0000
commitba8ce3875d09b88463da76148ba5d563049b089f (patch)
tree73868472e6ba7a948fadf49e12362c500cef1843 /docs/ERRORS.md
parent6da57c3a2c5c222591b0994acce79183b81d7f99 (diff)
docs: complete MODULES.md. minor updates elsewhere. prepare for hosting
Diffstat (limited to 'docs/ERRORS.md')
-rw-r--r--docs/ERRORS.md42
1 files changed, 18 insertions, 24 deletions
diff --git a/docs/ERRORS.md b/docs/ERRORS.md
index 4f99e7c..33c15d5 100644
--- a/docs/ERRORS.md
+++ b/docs/ERRORS.md
@@ -1,23 +1,6 @@
# Error Handling
-Puck's error handling is shamelessly stolen from Swift.
-It uses a combination of Option/Result types and try/catch/finally statements, and leans somewhat on Puck's metaprogramming capabilities.
-
-```puck
-func get_debug[T](): T =
- let value: Option[T] = self.unsafe_get(413)
- try:
- let value = value!
- catch Exception(e)
-
-
-try:
- ..
-catch:
- ..
-finally:
- print "No such errors"
-```
+Puck's error handling is shamelessly stolen from Swift. It uses a combination of `Option`/`Result` types and `try`/`catch` statements, and leans somewhat on Puck's metaprogramming capabilities.
There are several ways to handle errors in Puck. If the error is encoded in the type, one can:
1. `match` on the error
@@ -25,10 +8,9 @@ There are several ways to handle errors in Puck. If the error is encoded in the
3. propagate the error with `?`
4. throw the error with `!`
-If an error is thrown, one must explicitly handle (or disregard) it with a `try/catch` block.
-This method of error handling may feel more familiar to Java programmers.
+If an error is thrown, one **must** explicitly handle (or disregard) it with a `try/catch` block or risk runtime failure. This method of error handling may feel more familiar to Java programmers.
-## Errors as monads
+## Errors as Monads
Puck provides [`Option[T]`](std/default/options.pk) and a [`Result[T, E]`](std/default/results.pk) types, imported by default. These are `union` types and so must be pattern matched upon to be useful: but the standard library provides [a bevy of helper functions](std/default/results.pk).
Two in particular are of note. The `?` operator unwraps a Result or propagates its error up a function call (and may only be used in type-appropriate contexts). The `!` operator unwraps an Option or Result directly or throws an exception in the case of None or Error.
@@ -56,12 +38,12 @@ The utility of the provided helpers in [`std.options`](std/default/options.pk) a
A notable helpful type is the aliasing of `Result[T]` to `Result[T, ref Err]`, for when the particular error does not matter. This breaks `try`/`catch` exhaustion (as `ref Err` denotes a reference to *any* Error), but is particularly useful when used in conjunction with the propagation operator.
-## Errors as catchable exceptions
+## Errors as Catchable Exceptions
Errors raised by `raise`/`throw` (or subsequently the `!` operator) must be explicitly caught and handled via a `try`/`catch`/`finally` statement.
If an exception is not handled within a function body, the function must be explicitly marked as a throwing function via the `yeet` prefix (name to be determined). The compiler will statically determine which exceptions in particular are thrown from any given function, and enforce them to be explicitly handled or explicitly ignored.
-Errors are types. An error thrown from an unwrapped `Result[T, E]` is of type `E`. `catch` statements, then, may pattern match upon possible errors, behaving similarly to `of` branches.
+Despite functioning here as exceptions: errors remain types. An error thrown from an unwrapped `Result[T, E]` is of type `E`. `catch` statements, then, may pattern match upon possible errors, behaving similarly to `of` branches.
```puck
try:
@@ -76,7 +58,19 @@ This creates a distinction between two types of error handling, working in sync:
<!-- [nullable types](https://en.wikipedia.org/wiki/Nullable_type)?? -->
-## Unrecoverable exceptions
+## Errors and Void Functions
+
+Some functions do not return a value but can still fail: for example, setters.
+This can make it difficult to do monadic error handling elegantly: one could return a `Result[void, E]`, but...
+
+```puck
+pub func set[T](self: list[T], i: uint, val: T) =
+ if i > self.length:
+ raise IndexOutOfBounds
+ self.data.raw_set(offset = i, val)
+```
+
+## Unrecoverable Exceptions
There exist errors from which a program can not reasonably recover. These are the following:
- `Assertation Failure`: a call to an `assert` function has returned false at runtime.