---
title: Options and Results
canonical_url: https://mew-lang.org/language/options-and-results/
sidecar_url: https://mew-lang.org/language/options-and-results.md
content_hash: sha256:7c8894c7ac9dbad2a695becffebb40e772c33870188825fc3e34df336d6e4fe4
tokens: 864
uid: language.options-and-results
reading_time_minutes: 4
---

Language
# Options and Results

 
An `Option<T>` holds a value or nothing. A `Result<T, E>` holds a value or an error. Both are [unions](https://mew-lang.org/language/unions.md) from the [standard library](https://mew-lang.org/stdlib/std.md):

 
```mew
pub union Option<T> {
    none,
    some(T),
}
  
pub union Result<T, E> {
    ok(T),
    err(E),
}
```

 
Use them instead of returning `null` or a placeholder like `-1`.

 
## Making one

 
In a `return`, you can leave out the union's name, because the function's return type already says which union it is:

 
```mew
pub fn find_user(id: i32) -> Option<string> {
    if id == 1 {
        return .some("ada");
    }
  
    return .none;
}
  
pub fn divide(left: i32, right: i32) -> Result<i32, string> {
    if right == 0 {
        return .err("cannot divide by zero");
    }
  
    return .ok(left / right);
}
```

 
Elsewhere, write the type on the variable or on the case:

 
```mew
let held: Option<i32> = .some(3);
let failed = Result<i32, string>::err("no such file");
```

 
## Reading one

 
Use `match` to handle both cases:

 
```mew
match divide(10, 2) {
    .ok(value) => {
        println($"{value}");
    },
    .err(reason) => {
        println(reason);
    },
}
```

 
```
5
```

 
If you only care about one case, use `if let`. The name it binds only exists inside the block:

 
```mew
if let .some(name) = find_user(1) {
    println($"found {name}");
}
```

 
```
found ada
```

 
## Getting the value out

 
You don't always need a `match`. Both unions have methods for the common cases, and the [standard library](https://mew-lang.org/stdlib/std.md#optiont) lists all of them.

 
`unwrap_or` returns the value, or a fallback if there isn't one:

 
```mew
println(find_user(2).unwrap_or("nobody"));
println($"{divide(10, 0).unwrap_or(0)}");
```

 
```
nobody
0
```

 
`unwrap` returns the value and [panics](https://mew-lang.org/stdlib/std.md#functions) if there isn't one. Use it where a missing value means a bug in your program:

 
```mew
println($"{divide(10, 2).unwrap()}");
println($"{divide(10, 0).unwrap()}");
```

 
```
5
Unhandled error: unwrapped a result that failed
```

 
The message doesn't include the error, since `E` could be any type. Print `err()` yourself if you need it.

 
## Changing the value

 
`map` runs a function on the value, if there is one, and leaves a `none` or an error alone. `and_then` takes a function that can fail too, which lets you chain steps:

 
```mew
println($"{divide(10, 2).map(|n| n * 3).unwrap_or(0)}");
println($"{divide(100, 5).and_then(|n| divide(n, 2)).unwrap_or(0)}");
println($"{divide(100, 0).and_then(|n| divide(n, 2)).unwrap_or(-1)}");
```

 
```
15
10
-1
```

 
`map_err` runs a function on the error instead. `ok_or` turns an `Option` into a `Result`, with the error to use when there is no value:

 
```mew
let checked = divide(1, 0).map_err(|reason| $"checking failed: {reason}");
println(checked.err().unwrap_or(""));
  
let user = find_user(2).ok_or("no such user");
println(user.err().unwrap_or(""));
```

 
```
checking failed: cannot divide by zero
no such user
```

 
See [Error Propagation](https://mew-lang.org/language/error-propagation.md) for passing a `none` or an error on to the caller with `?`.

 
[Previous
                
                Lambdas](https://mew-lang.org/language/lambdas.md)[Next
                    
                Error Propagation](https://mew-lang.org/language/error-propagation.md)