Skip to content

Commit

Permalink
add Result to blockchain types (FuelLabs#3894)
Browse files Browse the repository at this point in the history
Added the Result type to the same page where Identity, ContractId, and
Address are covered. Definition was taken from standard library repo -
https://github.com/FuelLabs/sway/blob/master/sway-lib-std/src/result.sw

---------

Co-authored-by: Camila Ramos <[email protected]>
Co-authored-by: Mohammad Fawaz <[email protected]>
  • Loading branch information
3 people authored Feb 23, 2023
1 parent 91feedc commit a1cacd6
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 12 deletions.
1 change: 1 addition & 0 deletions docs/book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
- [Sway Language Basics](./basics/index.md)
- [Variables](./basics/variables.md)
- [Built-in Types](./basics/built_in_types.md)
- [Commonly Used Library Types](./basics/commonly_used_library_types.md)
- [Blockchain Types](./basics/blockchain_types.md)
- [Functions](./basics/functions.md)
- [Structs, Tuples, and Enums](./basics/structs_tuples_and_enums.md)
Expand Down
38 changes: 38 additions & 0 deletions docs/book/src/basics/commonly_used_library_types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Commonly Used Library Types

The Sway Standard Library is the foundation of portable Sway software, a set of minimal shared abstractions for the broader Sway ecosystem. It offers core types, library-defined operations on language primitives, native asset management, blockchain contextual operations, access control, storage management, and support for types from other VMs, among many other things. Reference the standard library docs [here](https://fuellabs.github.io/sway/master/std/index.html).

## `Result<T, E>`

Type `Result` is the type used for returning and propagating errors. It is an `enum` with two variants: `Ok(T)`, representing success and containing a value, and `Err(E)`, representing error and containing an error value. The `T` and `E` in this definition are type parameters, allowing `Result` to be generic and to be used with any types.

```sway
{{#include ../../../../sway-lib-std/src/result.sw:docs_result}}
```

Functions return `Result` whenever errors are expected and recoverable. Take the following example:

```sway
{{#include ../../../../examples/result/src/main.sw}}
```

## `Option<T>`

Type `Option` represents an optional value: every `Option` is either `Some` and contains a value, or `None`, and does not. `Option` types are very common in Sway code, as they have a number of uses:

- Initial values where `None` can be used as an initializer.
- Return value for otherwise reporting simple errors, where `None` is returned on error.

The implementation of `Option` matches on the variant: if it's `Ok` it returns the inner value, if it's `None`, it [reverts](https://github.com/FuelLabs/fuel-specs/blob/master/src/vm/instruction_set.md#rvrt-revert).

```sway
{{#include ../../../../sway-lib-std/src/option.sw:docs_option}}
```

`Option` is commonly paired with pattern matching to query the presence of a value and take action, allowing developers to choose how to handle the `None` case.

Below is an example that uses pattern matching to handle invalid divisions by 0 by returning an `Option`:

```sway
{{#include ../../../../examples/option/src/main.sw}}
```
10 changes: 10 additions & 0 deletions examples/Forc.lock
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,21 @@ name = 'native_token'
source = 'member'
dependencies = ['std']

[[package]]
name = 'option'
source = 'member'
dependencies = ['std']

[[package]]
name = 'ownership'
source = 'member'
dependencies = ['std']

[[package]]
name = 'result'
source = 'member'
dependencies = ['std']

[[package]]
name = 'signatures'
source = 'member'
Expand Down
2 changes: 2 additions & 0 deletions examples/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ members = [
"match_statements",
"msg_sender",
"native_token",
"option",
"ownership",
"ref_mut_params",
"result",
"signatures",
"storage_example",
"storage_map",
Expand Down
8 changes: 8 additions & 0 deletions examples/option/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "option"

[dependencies]
std = { path = "../../sway-lib-std" }
20 changes: 20 additions & 0 deletions examples/option/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
script;

fn divide(numerator: u64, denominator: u64) -> Option<u64> {
if denominator == 0 {
Option::None
} else {
Option::Some(numerator / denominator)
}
}

fn main() {
let result = divide(6, 2);
// Pattern match to retrieve the value
match result {
// The division was valid
Option::Some(x) => std::logging::log(x),
// The division was invalid
Option::None => std::logging::log("Cannot divide by 0"),
}
}
8 changes: 8 additions & 0 deletions examples/result/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "main.sw"
license = "Apache-2.0"
name = "result"

[dependencies]
std = { path = "../../sway-lib-std" }
21 changes: 21 additions & 0 deletions examples/result/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
script;

enum MyContractError {
DivisionByZero: (),
}

fn divide(numerator: u64, denominator: u64) -> Result<u64, MyContractError> {
if (denominator == 0) {
return Result::Err(MyContractError::DivisionByZero);
} else {
Result::Ok(numerator / denominator)
}
}

fn main() -> Result<u64, str[4]> {
let result = divide(20, 2);
match result {
Result::Ok(value) => Result::Ok(value),
Result::Err(MyContractError::DivisionByZero) => Result::Err("Fail"),
}
}
4 changes: 3 additions & 1 deletion sway-lib-std/src/option.sw
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ library option;
use ::result::Result;
use ::revert::revert;

/// The `Option` type. See the module level documentation for more.
// ANCHOR: docs_option
/// `Option` is a type that represents an optional value.
pub enum Option<T> {
/// No value.
None: (),
/// Some value of type `T`.
Some: T,
}
// ANCHOR_END: docs_option

// Type implementation
//
Expand Down
3 changes: 3 additions & 0 deletions sway-lib-std/src/result.sw
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,16 @@ library result;

use ::revert::revert;

// ANCHOR: docs_result
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
pub enum Result<T, E> {
/// Contains the success value.
Ok: T,
/// Contains the error value.
Err: E,
}
// ANCHOR_END: docs_result


// Type implementation
//
Expand Down
22 changes: 11 additions & 11 deletions sway-lsp/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ async fn go_to_definition_for_fields() {
req_uri: &uri,
req_line: 5,
req_char: 8,
def_line: 80,
def_line: 81,
def_start_char: 9,
def_end_char: 15,
def_path: "sway-lib-std/src/option.sw",
Expand Down Expand Up @@ -300,7 +300,7 @@ async fn go_to_definition_inside_turbofish() {
req_uri: &uri,
req_line: 15,
req_char: 12,
def_line: 80,
def_line: 81,
def_start_char: 9,
def_end_char: 15,
def_path: "sway-lib-std/src/option.sw",
Expand All @@ -320,7 +320,7 @@ async fn go_to_definition_inside_turbofish() {
req_uri: &uri,
req_line: 20,
req_char: 19,
def_line: 60,
def_line: 61,
def_start_char: 9,
def_end_char: 15,
def_path: "sway-lib-std/src/result.sw",
Expand Down Expand Up @@ -378,7 +378,7 @@ async fn go_to_definition_for_matches() {
req_uri: &uri,
req_line: 25,
req_char: 19,
def_line: 80,
def_line: 81,
def_start_char: 9,
def_end_char: 15,
def_path: "sway-lib-std/src/option.sw",
Expand All @@ -396,7 +396,7 @@ async fn go_to_definition_for_matches() {
req_uri: &uri,
req_line: 25,
req_char: 27,
def_line: 84,
def_line: 85,
def_start_char: 4,
def_end_char: 8,
def_path: "sway-lib-std/src/option.sw",
Expand All @@ -411,7 +411,7 @@ async fn go_to_definition_for_matches() {
req_uri: &uri,
req_line: 26,
req_char: 17,
def_line: 82,
def_line: 83,
def_start_char: 4,
def_end_char: 8,
def_path: "sway-lib-std/src/option.sw",
Expand Down Expand Up @@ -526,7 +526,7 @@ async fn go_to_definition_for_paths() {
req_uri: &uri,
req_line: 10,
req_char: 27,
def_line: 80,
def_line: 81,
def_start_char: 9,
def_end_char: 15,
def_path: "sway-lib-std/src/option.sw",
Expand Down Expand Up @@ -962,14 +962,14 @@ async fn go_to_definition_for_variables() {
definition_check_with_req_offset(&mut service, &mut go_to, 53, 21, &mut i).await;

// Complex type ascriptions
go_to.def_line = 60;
go_to.def_line = 61;
go_to.def_start_char = 9;
go_to.def_end_char = 15;
go_to.def_path = "sway-lib-std/src/result.sw";
definition_check_with_req_offset(&mut service, &mut go_to, 56, 22, &mut i).await;
definition_check_with_req_offset(&mut service, &mut go_to, 11, 31, &mut i).await;
definition_check_with_req_offset(&mut service, &mut go_to, 11, 60, &mut i).await;
go_to.def_line = 80;
go_to.def_line = 81;
go_to.def_path = "sway-lib-std/src/option.sw";
definition_check_with_req_offset(&mut service, &mut go_to, 56, 28, &mut i).await;
definition_check_with_req_offset(&mut service, &mut go_to, 11, 39, &mut i).await;
Expand Down Expand Up @@ -1054,7 +1054,7 @@ async fn go_to_definition_for_consts() {
definition_check_with_req_offset(&mut service, &mut go_to, 10, 17, &mut i).await;

// Complex type ascriptions
go_to.def_line = 80;
go_to.def_line = 81;
go_to.def_start_char = 9;
go_to.def_end_char = 15;
go_to.def_path = "sway-lib-std/src/option.sw";
Expand Down Expand Up @@ -1147,7 +1147,7 @@ async fn go_to_definition_for_structs() {
req_uri: &uri,
req_line: 16,
req_char: 11,
def_line: 80,
def_line: 81,
def_start_char: 9,
def_end_char: 15,
def_path: "sway-lib-std/src/option.sw",
Expand Down

0 comments on commit a1cacd6

Please sign in to comment.