Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract Option concept #301

Merged
merged 1 commit into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 0 additions & 88 deletions concepts/enums/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,92 +113,4 @@ msg.process(); // prints "quitting"
In many situations, enums can come in handy especially when used with the `match` flow as used above in the traits implementation.
Read more about the `match` flow in [The Cairo Book][match].

## The `Option` Enum and Its Advantages

The `Option` enum is a standard Cairo enum that represents the concept of an optional value.
It has two variants: `Some: T` and `None`.
`Some` variant has an associated value of type `T`, while `None` represents the absence of an associated value.

```rust
enum Option<T> {
Some: T,
None,
}
```

The `Option` enum is helpful because it allows you to explicitly represent the possibility of a value being absent, making your code more expressive and easier to reason about.
Using `Option` can also help prevent bugs caused by using uninitialized or unexpected `null` values.

The function below shows how the `Option` enum is used to return the index of the first element of an array with a given value, or return `None` if the element is absent.

```rust
fn find_value(mut arr: Span<felt252>, value: felt252) -> Option<usize> {
let mut result = Option::None;
let mut index = 0;

while let Option::Some(array_value) = arr
.pop_front() {
if (*array_value == value) {
result = Option::Some(index);
break;
};

index += 1;
};

result
}
```

## Concise Control Flow with `if let` and `while let`

The `if let` syntax combines `if` and `let` to handle specific pattern matches more concisely.

Using `match` to handle an `Option`:

```rust
let config_max: Option<felt252> = Option::Some(5);
match config_max {
Option::Some(max) => println!("The maximum is configured to be {}", max),
_ => (),
}
```

Using `if let` for the same logic:

```rust
let number: Option<felt252> = Option::Some(5);
if let Option::Some(max) = number {
println!("The maximum is configured to be {}", max);
}
```

You can also include an `else` with `if let`:

```rust
let coin: Coin = Coin::Quarter;
if let Coin::Quarter = coin {
println!("You got a quarter!");
} else {
println!("You got some other coin!");
}
```

The `while let` syntax loops over `Option` values, executing a block for each matching pattern.

```rust
fn main() {
let mut arr: Array<felt252> = array![1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut sum: felt252 = 0;
while let Option::Some(value) = arr.pop_front() {
sum += value;
}
println!("{}", sum);
}
```

There are other native enums, one of which is the `Result` enum, which allows for graceful error handling.
Read more about the `Result` enum in [The Cairo Book][results].

[match]: https://book.cairo-lang.org/ch06-02-the-match-control-flow-construct.html
[results]: https://book.cairo-lang.org/ch09-02-recoverable-errors.html#the-result-enum
4 changes: 0 additions & 4 deletions concepts/enums/links.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@
{
"url": "https://starknet-by-example.voyager.online/getting-started/cairo_cheatsheet/enums.html",
"description": "Starknet by Example section on Enums"
},
{
"url": "https://book.cairo-lang.org/ch06-03-concise-control-flow-with-if-let-and-while-let.html",
"description": "A section in the Cairo programming language book that discusses control flow with `if let` and `while let`"
}
]
7 changes: 7 additions & 0 deletions concepts/option/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"blurb": "Option<T>: a T which may or may not be there",
"authors": [
"0xNeshi"
],
"contributors": []
}
88 changes: 88 additions & 0 deletions concepts/option/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Options

The `Option` enum is a standard Cairo enum that represents the concept of an optional value.
It has two variants: `Some: T` and `None`.
`Some` variant has an associated value of type `T`, while `None` represents the absence of an associated value.

```rust
enum Option<T> {
Some: T,
None,
}
```

The `Option` enum is helpful because it allows you to explicitly represent the possibility of a value being absent, making your code more expressive and easier to reason about.
Using `Option` can also help prevent bugs caused by using uninitialized or unexpected `null` values.

The function below shows how the `Option` enum is used to return the index of the first element of an array with a given value, or return `None` if the element is absent.

```rust
fn find_value(mut arr: Span<felt252>, value: felt252) -> Option<usize> {
let mut result = Option::None;
let mut index = 0;

while let Option::Some(array_value) = arr
.pop_front() {
if (*array_value == value) {
result = Option::Some(index);
break;
};

index += 1;
};

result
}
```

## Concise Control Flow with `if let` and `while let`

The `if let` syntax combines `if` and `let` to handle specific pattern matches more concisely.

Using `match` to handle an `Option`:

```rust
let config_max: Option<felt252> = Option::Some(5);
match config_max {
Option::Some(max) => println!("The maximum is configured to be {}", max),
_ => (),
}
```

Using `if let` for the same logic:

```rust
let number: Option<felt252> = Option::Some(5);
if let Option::Some(max) = number {
println!("The maximum is configured to be {}", max);
}
```

You can also include an `else` with `if let`:

```rust
let coin: Coin = Coin::Quarter;
if let Coin::Quarter = coin {
println!("You got a quarter!");
} else {
println!("You got some other coin!");
}
```

The `while let` syntax loops over `Option` values, executing a block for each matching pattern.

```rust
fn main() {
let mut arr: Array<felt252> = array![1, 2, 3, 4, 5, 6, 7, 8, 9];
let mut sum: felt252 = 0;
while let Option::Some(value) = arr.pop_front() {
sum += value;
}
println!("{}", sum);
}
```

There are other native enums, one of which is the `Result` enum, which allows for graceful error handling.
Read more about the `Result` enum in [The Cairo Book][results].

[results]: https://book.cairo-lang.org/ch09-02-recoverable-errors.html#the-result-enum
4 changes: 4 additions & 0 deletions concepts/option/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Introduction

The standard library provides an enum called `Option` to help you express when a value may or may not exist.
You'll see it referred to as `Option<T>` where `T` is the type of the value you are working with.
10 changes: 10 additions & 0 deletions concepts/option/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"url": "https://book.cairo-lang.org/ch06-01-enums.html#the-option-enum-and-its-advantages",
"description": "The Option enum in The Cairo book"
},
{
"url": "https://book.cairo-lang.org/ch06-03-concise-control-flow-with-if-let-and-while-let.html",
"description": "A section in the Cairo programming language book that discusses control flow with `if let` and `while let`"
}
]
7 changes: 0 additions & 7 deletions concepts/options/.meta/config.json

This file was deleted.

1 change: 0 additions & 1 deletion concepts/options/about.md

This file was deleted.

1 change: 0 additions & 1 deletion concepts/options/introduction.md

This file was deleted.

1 change: 0 additions & 1 deletion concepts/options/links.json

This file was deleted.

8 changes: 4 additions & 4 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
"name": "Role Playing Game",
"uuid": "1b014752-c3a4-4250-9483-89696864461b",
"concepts": [
"options"
"option"
],
"prerequisites": [
"structs",
Expand All @@ -230,7 +230,7 @@
"type-conversion"
],
"prerequisites": [
"options",
"option",
"printing"
],
"status": "wip"
Expand Down Expand Up @@ -918,8 +918,8 @@
},
{
"uuid": "0bd2a321-f169-49a9-83d6-7d91193db915",
"slug": "options",
"name": "Options"
"slug": "option",
"name": "Option"
},
{
"uuid": "c11a8aa5-cda4-4d02-a477-3db3d3ca5acf",
Expand Down
Loading