Error Handling - cyxigo/wi GitHub Wiki

Introduction

While you were reading, my dear friend, you may have noticed compile and runtime errors. While we can't do anything about the former, we actually can do something about the latter.

std::try

What if you know some code can cause a runtime error? For example:

select := |n, ...args| => args[n];
std::puts(select(2));

This will cause a runtime error:

runtime error: array index out of range: 2
   --> file.wi:1 in select()
   --> file.wi:2 in main function

But we can use a handy builtin function called std::try – it accepts a function as the first argument, and all the next arguments get passed as the function's parameters:

select := |n, ...args| => args[n];
result := std::try(select, 2);

if (!result.ok) {
    std::puts("oops!");
} else {
    std::puts(result.value);
}

std::try returns an object with fields ok, value, and error:

  • ok: a boolean value, true if no errors or false otherwise
  • value: function's returned value or null if any error occurred
  • error: error message, what actually has happened

Another example:

select := |n, ...args| => args[n];
result := std::try(select, 2);

if (!result.ok) {
    std::puts("oops! this happened:", result.error);
} else {
    std::puts(result.value);
}

We'd get:

oops! this happened:
array index out of range: 2

We can also use std::try inside of the select, just wrap that dangerous code in a function:

select := |n, ...args| => std::try(|x| => args[x], n).value || -1;
std::puts(select(2));          %% -1
std::puts(select(2, 3, 4, 5)); %% 5

[!NOTE] If you didn't understand this cool looking one-liner: since std::try sets value to null on error AND null is falsy we can use || (logical OR) to enforce some default value in case of an error! In this case it's -1.

[!TIP] You can even do cool stuff like combining std::error with std::try! Surely this will come in handy...

Next: Attributes