diff options
-rw-r--r-- | src/gleam/option.gleam | 412 | ||||
-rw-r--r-- | test/gleam/option_test.gleam | 230 |
2 files changed, 319 insertions, 323 deletions
diff --git a/src/gleam/option.gleam b/src/gleam/option.gleam index feb6f56..f72f552 100644 --- a/src/gleam/option.gleam +++ b/src/gleam/option.gleam @@ -1,227 +1,225 @@ -if erlang { - import gleam/list +import gleam/list - /// Option represents a value that may be present or not. Some means the value is - /// present, None means the value is not. - /// - /// This is Gleam's alternative to having a value that could be Null, as is - /// possible in some other languages. - /// - pub type Option(a) { - Some(a) - None - } +/// Option represents a value that may be present or not. Some means the value is +/// present, None means the value is not. +/// +/// This is Gleam's alternative to having a value that could be Null, as is +/// possible in some other languages. +/// +pub type Option(a) { + Some(a) + None +} - /// Combines a list of options into a single option. - /// If all elements in the list are Some then returns a Some holding the list of values. - /// If any element is None then returns None. - /// - /// ## Examples - /// - /// ``` - /// > all([Some(1), Some(2)]) - /// Some([1, 2]) - /// - /// > all([Some(1), None]) - /// None - /// ``` - /// - pub fn all(list: List(Option(a))) -> Option(List(a)) { - list.fold_right( - list, - from: Some([]), - with: fn(item, acc) { - case acc, item { - Some(values), Some(value) -> Some([value, ..values]) - _, _ -> None - } - }, - ) - } +/// Combines a list of options into a single option. +/// If all elements in the list are Some then returns a Some holding the list of values. +/// If any element is None then returns None. +/// +/// ## Examples +/// +/// ``` +/// > all([Some(1), Some(2)]) +/// Some([1, 2]) +/// +/// > all([Some(1), None]) +/// None +/// ``` +/// +pub fn all(list: List(Option(a))) -> Option(List(a)) { + list.fold_right( + list, + from: Some([]), + with: fn(item, acc) { + case acc, item { + Some(values), Some(value) -> Some([value, ..values]) + _, _ -> None + } + }, + ) +} - /// Checks whether the option is a Some value. - /// - /// ## Examples - /// - /// > is_some(Some(1)) - /// True - /// - /// > is_some(None) - /// False - /// - pub fn is_some(option: Option(a)) -> Bool { - option != None - } +/// Checks whether the option is a Some value. +/// +/// ## Examples +/// +/// > is_some(Some(1)) +/// True +/// +/// > is_some(None) +/// False +/// +pub fn is_some(option: Option(a)) -> Bool { + option != None +} - /// Checks whether the option is a None value. - /// - /// ## Examples - /// - /// > is_none(Some(1)) - /// False - /// - /// > is_none(None) - /// True - /// - pub fn is_none(option: Option(a)) -> Bool { - option == None - } +/// Checks whether the option is a None value. +/// +/// ## Examples +/// +/// > is_none(Some(1)) +/// False +/// +/// > is_none(None) +/// True +/// +pub fn is_none(option: Option(a)) -> Bool { + option == None +} - /// Converts an Option type to a Result type - /// - /// ## Examples - /// - /// > to_result(Some(1), "some_error") - /// Ok(1) - /// > to_result(None, "some_error") - /// Error("some_error") - /// - pub fn to_result(option: Option(a), e) -> Result(a, e) { - case option { - Some(a) -> Ok(a) - _ -> Error(e) - } +/// Converts an Option type to a Result type +/// +/// ## Examples +/// +/// > to_result(Some(1), "some_error") +/// Ok(1) +/// > to_result(None, "some_error") +/// Error("some_error") +/// +pub fn to_result(option: Option(a), e) -> Result(a, e) { + case option { + Some(a) -> Ok(a) + _ -> Error(e) } +} - /// Converts a Result type to an Option type - /// - /// ## Examples - /// - /// > from_result(Ok(1)) - /// Some(1) - /// > from_result(Error"some_error")) - /// None - /// - pub fn from_result(result: Result(a, e)) -> Option(a) { - case result { - Ok(a) -> Some(a) - _ -> None - } +/// Converts a Result type to an Option type +/// +/// ## Examples +/// +/// > from_result(Ok(1)) +/// Some(1) +/// > from_result(Error"some_error")) +/// None +/// +pub fn from_result(result: Result(a, e)) -> Option(a) { + case result { + Ok(a) -> Some(a) + _ -> None } +} - /// Extracts the value from an option, returning a default value if there is none. - /// - /// ## Examples - /// - /// > unwrap(Some(1), 0) - /// 1 - /// - /// > unwrap(None, 0) - /// 0 - /// - pub fn unwrap(option: Option(a), or default: a) -> a { - case option { - Some(x) -> x - None -> default - } +/// Extracts the value from an option, returning a default value if there is none. +/// +/// ## Examples +/// +/// > unwrap(Some(1), 0) +/// 1 +/// +/// > unwrap(None, 0) +/// 0 +/// +pub fn unwrap(option: Option(a), or default: a) -> a { + case option { + Some(x) -> x + None -> default } +} - /// Updates a value held within the Some of an Option by calling a given function - /// on it. - /// - /// If the option is a None rather than Some the function is not called and the - /// option stays the same. - /// - /// ## Examples - /// - /// > map(over: Some(1), with: fn(x) { x + 1 }) - /// Some(2) - /// - /// > map(over: None, with: fn(x) { x + 1 }) - /// None - /// - pub fn map(over option: Option(a), with fun: fn(a) -> b) -> Option(b) { - case option { - Some(x) -> Some(fun(x)) - None -> None - } +/// Updates a value held within the Some of an Option by calling a given function +/// on it. +/// +/// If the option is a None rather than Some the function is not called and the +/// option stays the same. +/// +/// ## Examples +/// +/// > map(over: Some(1), with: fn(x) { x + 1 }) +/// Some(2) +/// +/// > map(over: None, with: fn(x) { x + 1 }) +/// None +/// +pub fn map(over option: Option(a), with fun: fn(a) -> b) -> Option(b) { + case option { + Some(x) -> Some(fun(x)) + None -> None } +} - /// Merges a nested Option into a single layer. - /// - /// ## Examples - /// - /// > flatten(Some(Some(1))) - /// Some(1) - /// - /// > flatten(Some(None)) - /// None - /// - /// > flatten(None) - /// None - /// - pub fn flatten(option: Option(Option(a))) -> Option(a) { - case option { - Some(x) -> x - None -> None - } +/// Merges a nested Option into a single layer. +/// +/// ## Examples +/// +/// > flatten(Some(Some(1))) +/// Some(1) +/// +/// > flatten(Some(None)) +/// None +/// +/// > flatten(None) +/// None +/// +pub fn flatten(option: Option(Option(a))) -> Option(a) { + case option { + Some(x) -> x + None -> None } +} - /// Updates a value held within the Some of an Option by calling a given function - /// on it, where the given function also returns an Option. The two Options are - /// then merged together into one Option. - /// - /// If the Option is a None rather than Some the function is not called and the - /// Option stays the same. - /// - /// This function is the equivalent of calling `map` followed by `flatten`, and - /// it is useful for chaining together multiple functions that return Options. - /// - /// ## Examples - /// - /// > then(Some(1), fn(x) { Some(x + 1) }) - /// Some(2) - /// - /// > then(Some(1), fn(x) { Some(#("a", x)) }) - /// Some(#("a", 1)) - /// - /// > then(Some(1), fn(x) { None }) - /// None - /// - /// > then(None, fn(x) { Some(x + 1) }) - /// None - /// - pub fn then(option: Option(a), apply fun: fn(a) -> Option(b)) -> Option(b) { - case option { - Some(x) -> fun(x) - None -> None - } +/// Updates a value held within the Some of an Option by calling a given function +/// on it, where the given function also returns an Option. The two Options are +/// then merged together into one Option. +/// +/// If the Option is a None rather than Some the function is not called and the +/// Option stays the same. +/// +/// This function is the equivalent of calling `map` followed by `flatten`, and +/// it is useful for chaining together multiple functions that return Options. +/// +/// ## Examples +/// +/// > then(Some(1), fn(x) { Some(x + 1) }) +/// Some(2) +/// +/// > then(Some(1), fn(x) { Some(#("a", x)) }) +/// Some(#("a", 1)) +/// +/// > then(Some(1), fn(x) { None }) +/// None +/// +/// > then(None, fn(x) { Some(x + 1) }) +/// None +/// +pub fn then(option: Option(a), apply fun: fn(a) -> Option(b)) -> Option(b) { + case option { + Some(x) -> fun(x) + None -> None } +} - /// Returns the first value if it is Some, otherwise return the second value. - /// - /// ## Examples - /// - /// > or(Some(1), Some(2)) - /// Some(1) - /// - /// > or(Some(1), None) - /// Some(1) - /// - /// > or(None, Some(2)) - /// Some(2) - /// - /// > or(None, None) - /// None - /// - pub fn or(first: Option(a), second: Option(a)) -> Option(a) { - case first { - Some(_) -> first - None -> second - } +/// Returns the first value if it is Some, otherwise return the second value. +/// +/// ## Examples +/// +/// > or(Some(1), Some(2)) +/// Some(1) +/// +/// > or(Some(1), None) +/// Some(1) +/// +/// > or(None, Some(2)) +/// Some(2) +/// +/// > or(None, None) +/// None +/// +pub fn or(first: Option(a), second: Option(a)) -> Option(a) { + case first { + Some(_) -> first + None -> second } +} - /// Given a list of options - /// Return only the values inside Some - /// - /// ## Examples - /// - /// ``` - /// > values([Some(1), None, Some(3)]) - /// [1, 3] - /// ``` - /// - pub fn values(options: List(Option(a))) -> List(a) { - list.filter_map(options, fn(op) { to_result(op, "") }) - } +/// Given a list of options +/// Return only the values inside Some +/// +/// ## Examples +/// +/// ``` +/// > values([Some(1), None, Some(3)]) +/// [1, 3] +/// ``` +/// +pub fn values(options: List(Option(a))) -> List(a) { + list.filter_map(options, fn(op) { to_result(op, "") }) } diff --git a/test/gleam/option_test.gleam b/test/gleam/option_test.gleam index 32b1df6..35c9eb3 100644 --- a/test/gleam/option_test.gleam +++ b/test/gleam/option_test.gleam @@ -1,117 +1,115 @@ -if erlang { - import gleam/should - import gleam/option.{None, Some} - - pub fn all_test() { - option.all([Some(1), Some(2), Some(3)]) - |> should.equal(Some([1, 2, 3])) - - option.all([Some(1), None, Some(3)]) - |> should.equal(None) - } - - pub fn is_some_test() { - option.is_some(Some(1)) - |> should.be_true - - option.is_some(None) - |> should.be_false - } - - pub fn is_none_test() { - option.is_none(Some(1)) - |> should.be_false - - option.is_none(None) - |> should.be_true - } - - pub fn to_result_test() { - option.to_result(Some(1), "possible_error") - |> should.equal(Ok(1)) - - option.to_result(None, "possible_error") - |> should.equal(Error("possible_error")) - } - - pub fn from_result_test() { - option.from_result(Ok(1)) - |> should.equal(Some(1)) - - option.from_result(Error("some_error")) - |> should.equal(None) - } - - pub fn unwrap_option_test() { - option.unwrap(Some(1), 0) - |> should.equal(1) - - option.unwrap(None, 0) - |> should.equal(0) - } - - pub fn map_option_test() { - Some(1) - |> option.map(fn(x) { x + 1 }) - |> should.equal(Some(2)) - - Some(1) - |> option.map(fn(_) { "2" }) - |> should.equal(Some("2")) - - None - |> option.map(fn(x) { x + 1 }) - |> should.equal(None) - } - - pub fn flatten_option_test() { - Some(Some(1)) - |> option.flatten() - |> should.equal(Some(1)) - - Some(None) - |> option.flatten() - |> should.equal(None) - - None - |> option.flatten() - |> should.equal(None) - } - - pub fn then_option_test() { - Some(1) - |> option.then(fn(x) { Some(x + 1) }) - |> should.equal(Some(2)) - - Some(1) - |> option.then(fn(_) { Some("2") }) - |> should.equal(Some("2")) - - None - |> option.then(fn(x) { Some(x + 1) }) - |> should.equal(None) - } - - pub fn or_option_test() { - Some(1) - |> option.or(Some(2)) - |> should.equal(Some(1)) - - Some(1) - |> option.or(None) - |> should.equal(Some(1)) - - None - |> option.or(Some(2)) - |> should.equal(Some(2)) - - None - |> option.or(None) - |> should.equal(None) - } - - pub fn values_test() { - option.values([Some(1), None, Some(3)]) - |> should.equal([1, 3]) - } +import gleam/should +import gleam/option.{None, Some} + +pub fn all_test() { + option.all([Some(1), Some(2), Some(3)]) + |> should.equal(Some([1, 2, 3])) + + option.all([Some(1), None, Some(3)]) + |> should.equal(None) +} + +pub fn is_some_test() { + option.is_some(Some(1)) + |> should.be_true + + option.is_some(None) + |> should.be_false +} + +pub fn is_none_test() { + option.is_none(Some(1)) + |> should.be_false + + option.is_none(None) + |> should.be_true +} + +pub fn to_result_test() { + option.to_result(Some(1), "possible_error") + |> should.equal(Ok(1)) + + option.to_result(None, "possible_error") + |> should.equal(Error("possible_error")) +} + +pub fn from_result_test() { + option.from_result(Ok(1)) + |> should.equal(Some(1)) + + option.from_result(Error("some_error")) + |> should.equal(None) +} + +pub fn unwrap_option_test() { + option.unwrap(Some(1), 0) + |> should.equal(1) + + option.unwrap(None, 0) + |> should.equal(0) +} + +pub fn map_option_test() { + Some(1) + |> option.map(fn(x) { x + 1 }) + |> should.equal(Some(2)) + + Some(1) + |> option.map(fn(_) { "2" }) + |> should.equal(Some("2")) + + None + |> option.map(fn(x) { x + 1 }) + |> should.equal(None) +} + +pub fn flatten_option_test() { + Some(Some(1)) + |> option.flatten() + |> should.equal(Some(1)) + + Some(None) + |> option.flatten() + |> should.equal(None) + + None + |> option.flatten() + |> should.equal(None) +} + +pub fn then_option_test() { + Some(1) + |> option.then(fn(x) { Some(x + 1) }) + |> should.equal(Some(2)) + + Some(1) + |> option.then(fn(_) { Some("2") }) + |> should.equal(Some("2")) + + None + |> option.then(fn(x) { Some(x + 1) }) + |> should.equal(None) +} + +pub fn or_option_test() { + Some(1) + |> option.or(Some(2)) + |> should.equal(Some(1)) + + Some(1) + |> option.or(None) + |> should.equal(Some(1)) + + None + |> option.or(Some(2)) + |> should.equal(Some(2)) + + None + |> option.or(None) + |> should.equal(None) +} + +pub fn values_test() { + option.values([Some(1), None, Some(3)]) + |> should.equal([1, 3]) } |