Results
Type | Syntax | Purpose | Application |
---|---|---|---|
Result | Result.Result<T, E> where T is the success type and E is the error type. | Represents success or failure. | When an operation can either succeed or fail. |
While options are a built-in type, the Result
is defined as a variant type:
type Result<Ok, Err> = { #ok : Ok; #err : Err }
Because of the second type parameter Err
, the Result
type lets you select the type used to describe errors.
Here’s a simple function that validates a username. If it's non-empty, it will return a greeting of type Text
. If not, it will return an error of type Text
.
import Result "mo:base/Result";
func greet(name : Text) : Result.Result<Text, Text> {
if (name.size() == 0) #err "Name is empty" else #ok ("Hello" # name);
};
Pattern matching with Result
When a Motoko value has type Result<T, E>
, it is either a success, written #ok value
, or a failure, written #err error
. The fundamental way to access the contents is to use a switch
expression that explicitly handles both cases.
switch
import Result "mo:base/Result";
func greet(name : Text) : Result.Result<Text, Text> {
if (name.size() == 0) #err "Name is empty" else #ok ("Hello " # name);
};
let result = greet("Motoko");
switch (result){
case (#ok message) {
message
};
case (#err error) {
error
};
} // "Hello Motoko"
The verbosity of switch
expressions can make code harder to read, so Motoko also offers additional ways to handle Result
.
let else
Values can be extracted from Result
using the let ... else
pattern. This can be preferable to a switch
expression when only the success case
is needed, and the else branch can cleanly handle or exit on failure. It allows concise early returns or alternative flows when the result is #err
.
import Result "mo:base/Result";
func greet(name : Text) : Result.Result<Text, Text> {
if (name.size() == 0) #err "Name is empty" else #ok ("Hello " # name);
};
func safeGreet(name : Text) : Text {
let #ok greeting = greet(name) else return "Default greeting: Hi!";
greeting
};
safeGreet(""); // returns "Default greeting: Hi!"
In safeGreet
, the else
branch of the let
expression allows the function to exit early with a default greeting when the result of greet
is an error (i.e., does not match #ok greeting
but instead returns #err ...
). However, this pattern does not provide access to the actual error value.
If you need to handle or inspect the error, it's better to use a switch
statement, which gives you explicit access to both #ok
and #err
cases.