-
Notifications
You must be signed in to change notification settings - Fork 380
feat: Add Option<T> to noir stdlib
#1781
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
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
7fb4135
Add Option
c53538e
Fix path
3bb70fd
Add option test
6882fff
Merge branch 'master' into jf/option
2be7ed2
Move test
7b7cef0
Merge branch 'master' into jf/option
cdee978
Add docs and filter, flatten methods
5cbfb9c
Fix stdlib
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| [package] | ||
| name = "option" | ||
| authors = [""] | ||
| compiler_version = "0.7.0" | ||
|
|
||
| [dependencies] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| use dep::std::option::Option; | ||
|
|
||
| fn main() { | ||
| let none = Option::none(); | ||
| let some = Option::some(3); | ||
|
|
||
| assert(none.is_none()); | ||
| assert(some.is_some()); | ||
|
|
||
| assert(some.unwrap() == 3); | ||
|
|
||
| assert(none.unwrap_or(2) == 2); | ||
| assert(some.unwrap_or(2) == 3); | ||
|
|
||
| assert(none.unwrap_or_else(|| 5) == 5); | ||
| assert(some.unwrap_or_else(|| 5) == 3); | ||
|
|
||
| assert(none.map(|x| x * 2).is_none()); | ||
| assert(some.map(|x| x * 2).unwrap() == 6); | ||
|
|
||
| assert(none.map_or(0, |x| x * 2) == 0); | ||
| assert(some.map_or(0, |x| x * 2) == 6); | ||
|
|
||
| assert(none.map_or_else(|| 0, |x| x * 2) == 0); | ||
| assert(some.map_or_else(|| 0, |x| x * 2) == 6); | ||
|
|
||
| assert(none.and(none).is_none()); | ||
| assert(none.and(some).is_none()); | ||
| assert(some.and(none).is_none()); | ||
| assert(some.and(some).is_some()); | ||
|
|
||
| let add1_u64 = |value: Field| Option::some(value as u64 + 1); | ||
|
|
||
| assert(none.and_then(|_value| Option::none()).is_none()); | ||
| assert(none.and_then(add1_u64).is_none()); | ||
| assert(some.and_then(|_value| Option::none()).is_none()); | ||
| assert(some.and_then(add1_u64).unwrap() == 4); | ||
|
|
||
| assert(none.or(none).is_none()); | ||
| assert(none.or(some).is_some()); | ||
| assert(some.or(none).is_some()); | ||
| assert(some.or(some).is_some()); | ||
|
|
||
| assert(none.or_else(|| Option::none()).is_none()); | ||
| assert(none.or_else(|| Option::some(5)).is_some()); | ||
| assert(some.or_else(|| Option::none()).is_some()); | ||
| assert(some.or_else(|| Option::some(5)).is_some()); | ||
|
|
||
| assert(none.xor(none).is_none()); | ||
| assert(none.xor(some).is_some()); | ||
| assert(some.xor(none).is_some()); | ||
| assert(some.xor(some).is_none()); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,157 @@ | ||
| struct Option<T> { | ||
| _is_some: bool, | ||
| value: T, | ||
| } | ||
|
|
||
| impl<T> Option<T> { | ||
| /// Constructs a None value | ||
| fn none() -> Self { | ||
| Self { _is_some: false, value: crate::unsafe::zeroed() } | ||
| } | ||
|
|
||
| /// Constructs a Some wrapper around the given value | ||
| fn some(value: T) -> Self { | ||
| Self { _is_some: true, value } | ||
| } | ||
|
|
||
| /// True if this Option is None | ||
| fn is_none(self) -> bool { | ||
| !self._is_some | ||
| } | ||
|
|
||
| /// True if this Option is Some | ||
| fn is_some(self) -> bool { | ||
| self._is_some | ||
| } | ||
|
|
||
| /// Asserts `self.is_some()` and returns the wrapped value. | ||
| fn unwrap(self) -> T { | ||
| assert(self._is_some); | ||
| self.value | ||
| } | ||
|
|
||
| /// Returns the wrapped value if `self.is_some()`. Otherwise, returns the given default value. | ||
| fn unwrap_or(self, default: T) -> T { | ||
| if self._is_some { | ||
| self.value | ||
| } else { | ||
| default | ||
| } | ||
| } | ||
|
|
||
| /// Returns the wrapped value if `self.is_some()`. Otherwise, calls the given function to return | ||
| /// a default value. | ||
| fn unwrap_or_else(self, default: fn() -> T) -> T { | ||
| if self._is_some { | ||
| self.value | ||
| } else { | ||
| default() | ||
| } | ||
| } | ||
|
|
||
| /// If self is `Some(x)`, this returns `Some(f(x))`. Otherwise, this returns `None`. | ||
| fn map<U>(self, f: fn(T) -> U) -> Option<U> { | ||
| if self._is_some { | ||
| Option::some(f(self.value)) | ||
| } else { | ||
| Option::none() | ||
| } | ||
| } | ||
|
|
||
| /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns the given default value. | ||
| fn map_or<U>(self, default: U, f: fn(T) -> U) -> U { | ||
| if self._is_some { | ||
| f(self.value) | ||
| } else { | ||
| default | ||
| } | ||
| } | ||
|
|
||
| /// If self is `Some(x)`, this returns `f(x)`. Otherwise, this returns `default()`. | ||
| fn map_or_else<U>(self, default: fn() -> U, f: fn(T) -> U) -> U { | ||
| if self._is_some { | ||
| f(self.value) | ||
| } else { | ||
| default() | ||
| } | ||
| } | ||
|
|
||
| /// Returns None if self is None. Otherwise, this returns `other`. | ||
| fn and(self, other: Self) -> Self { | ||
| if self.is_none() { | ||
| Option::none() | ||
| } else { | ||
| other | ||
| } | ||
| } | ||
|
|
||
| /// If self is None, this returns None. Otherwise, this calls the given function | ||
| /// with the Some value contained within self, and returns the result of that call. | ||
| /// | ||
| /// In some languages this function is called `flat_map` or `bind`. | ||
| fn and_then<U>(self, f: fn(T) -> Option<U>) -> Option<U> { | ||
| if self._is_some { | ||
| f(self.value) | ||
| } else { | ||
| Option::none() | ||
| } | ||
| } | ||
|
|
||
| /// If self is Some, return self. Otherwise, return `other`. | ||
| fn or(self, other: Self) -> Self { | ||
| if self._is_some { | ||
| self | ||
| } else { | ||
| other | ||
| } | ||
| } | ||
|
|
||
| /// If self is Some, return self. Otherwise, return `default()`. | ||
| fn or_else<U>(self, default: fn() -> Self) -> Self { | ||
| if self._is_some { | ||
| self | ||
| } else { | ||
| default() | ||
| } | ||
| } | ||
|
|
||
| // If only one of the two Options is Some, return that option. | ||
| // Otherwise, if both options are Some or both are None, None is returned. | ||
| fn xor(self, other: Self) -> Self { | ||
| if self._is_some { | ||
| if other._is_some { | ||
| Option::none() | ||
| } else { | ||
| self | ||
| } | ||
| } else if other._is_some { | ||
| other | ||
| } else { | ||
| Option::none() | ||
| } | ||
| } | ||
|
|
||
| /// Returns `Some(x)` if self is `Some(x)` and `predicate(x)` is true. | ||
| /// Otherwise, this returns `None` | ||
| fn filter(self, predicate: fn(T) -> bool) -> Self { | ||
| if self._is_some { | ||
| if predicate(self.value) { | ||
| self | ||
| } else { | ||
| Option::none() | ||
| } | ||
| } else { | ||
| Option::none() | ||
| } | ||
| } | ||
|
|
||
| /// Flattens an Option<Option<T>> into a Option<T>. | ||
| /// This returns None if the outer Option is None. Otherwise, this returns the inner Option. | ||
| fn flatten(option: Option<Option<T>>) -> Option<T> { | ||
| if option._is_some { | ||
| option.value | ||
| } else { | ||
| Option::none() | ||
| } | ||
| } | ||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.