419 lines
7.4 KiB
JavaScript
419 lines
7.4 KiB
JavaScript
import {
|
|
Ok,
|
|
Error,
|
|
toList,
|
|
Empty as $Empty,
|
|
prepend as listPrepend,
|
|
CustomType as $CustomType,
|
|
isEqual,
|
|
} from "../gleam.mjs";
|
|
|
|
export class Some extends $CustomType {
|
|
constructor($0) {
|
|
super();
|
|
this[0] = $0;
|
|
}
|
|
}
|
|
export const Option$Some = ($0) => new Some($0);
|
|
export const Option$isSome = (value) => value instanceof Some;
|
|
export const Option$Some$0 = (value) => value[0];
|
|
|
|
export class None extends $CustomType {}
|
|
export const Option$None = () => new None();
|
|
export const Option$isNone = (value) => value instanceof None;
|
|
|
|
function reverse_and_prepend(loop$prefix, loop$suffix) {
|
|
while (true) {
|
|
let prefix = loop$prefix;
|
|
let suffix = loop$suffix;
|
|
if (prefix instanceof $Empty) {
|
|
return suffix;
|
|
} else {
|
|
let first = prefix.head;
|
|
let rest = prefix.tail;
|
|
loop$prefix = rest;
|
|
loop$suffix = listPrepend(first, suffix);
|
|
}
|
|
}
|
|
}
|
|
|
|
function reverse(list) {
|
|
return reverse_and_prepend(list, toList([]));
|
|
}
|
|
|
|
function all_loop(loop$list, loop$acc) {
|
|
while (true) {
|
|
let list = loop$list;
|
|
let acc = loop$acc;
|
|
if (list instanceof $Empty) {
|
|
return new Some(reverse(acc));
|
|
} else {
|
|
let $ = list.head;
|
|
if ($ instanceof Some) {
|
|
let rest = list.tail;
|
|
let first = $[0];
|
|
loop$list = rest;
|
|
loop$acc = listPrepend(first, acc);
|
|
} else {
|
|
return new None();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Combines a list of `Option`s 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
|
|
*
|
|
* ```gleam
|
|
* all([Some(1), Some(2)])
|
|
* // -> Some([1, 2])
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* all([Some(1), None])
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function all(list) {
|
|
return all_loop(list, toList([]));
|
|
}
|
|
|
|
/**
|
|
* Checks whether the `Option` is a `Some` value.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* is_some(Some(1))
|
|
* // -> True
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* is_some(None)
|
|
* // -> False
|
|
* ```
|
|
*/
|
|
export function is_some(option) {
|
|
return !isEqual(option, new None());
|
|
}
|
|
|
|
/**
|
|
* Checks whether the `Option` is a `None` value.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* is_none(Some(1))
|
|
* // -> False
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* is_none(None)
|
|
* // -> True
|
|
* ```
|
|
*/
|
|
export function is_none(option) {
|
|
return isEqual(option, new None());
|
|
}
|
|
|
|
/**
|
|
* Converts an `Option` type to a `Result` type.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* to_result(Some(1), "some_error")
|
|
* // -> Ok(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* to_result(None, "some_error")
|
|
* // -> Error("some_error")
|
|
* ```
|
|
*/
|
|
export function to_result(option, e) {
|
|
if (option instanceof Some) {
|
|
let a = option[0];
|
|
return new Ok(a);
|
|
} else {
|
|
return new Error(e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts a `Result` type to an `Option` type.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* from_result(Ok(1))
|
|
* // -> Some(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* from_result(Error("some_error"))
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function from_result(result) {
|
|
if (result instanceof Ok) {
|
|
let a = result[0];
|
|
return new Some(a);
|
|
} else {
|
|
return new None();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extracts the value from an `Option`, returning a default value if there is none.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* unwrap(Some(1), 0)
|
|
* // -> 1
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* unwrap(None, 0)
|
|
* // -> 0
|
|
* ```
|
|
*/
|
|
export function unwrap(option, default$) {
|
|
if (option instanceof Some) {
|
|
let x = option[0];
|
|
return x;
|
|
} else {
|
|
return default$;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extracts the value from an `Option`, evaluating the default function if the option is `None`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* lazy_unwrap(Some(1), fn() { 0 })
|
|
* // -> 1
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* lazy_unwrap(None, fn() { 0 })
|
|
* // -> 0
|
|
* ```
|
|
*/
|
|
export function lazy_unwrap(option, default$) {
|
|
if (option instanceof Some) {
|
|
let x = option[0];
|
|
return x;
|
|
} else {
|
|
return 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
|
|
*
|
|
* ```gleam
|
|
* map(over: Some(1), with: fn(x) { x + 1 })
|
|
* // -> Some(2)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* map(over: None, with: fn(x) { x + 1 })
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function map(option, fun) {
|
|
if (option instanceof Some) {
|
|
let x = option[0];
|
|
return new Some(fun(x));
|
|
} else {
|
|
return option;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Merges a nested `Option` into a single layer.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* flatten(Some(Some(1)))
|
|
* // -> Some(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* flatten(Some(None))
|
|
* // -> None
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* flatten(None)
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function flatten(option) {
|
|
if (option instanceof Some) {
|
|
let x = option[0];
|
|
return x;
|
|
} else {
|
|
return option;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 `Option`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* then(Some(1), fn(x) { Some(x + 1) })
|
|
* // -> Some(2)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* then(Some(1), fn(x) { Some(#("a", x)) })
|
|
* // -> Some(#("a", 1))
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* then(Some(1), fn(_) { None })
|
|
* // -> None
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* then(None, fn(x) { Some(x + 1) })
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function then$(option, fun) {
|
|
if (option instanceof Some) {
|
|
let x = option[0];
|
|
return fun(x);
|
|
} else {
|
|
return option;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the first value if it is `Some`, otherwise returns the second value.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* or(Some(1), Some(2))
|
|
* // -> Some(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* or(Some(1), None)
|
|
* // -> Some(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* or(None, Some(2))
|
|
* // -> Some(2)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* or(None, None)
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function or(first, second) {
|
|
if (first instanceof Some) {
|
|
return first;
|
|
} else {
|
|
return second;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* lazy_or(Some(1), fn() { Some(2) })
|
|
* // -> Some(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* lazy_or(Some(1), fn() { None })
|
|
* // -> Some(1)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* lazy_or(None, fn() { Some(2) })
|
|
* // -> Some(2)
|
|
* ```
|
|
*
|
|
* ```gleam
|
|
* lazy_or(None, fn() { None })
|
|
* // -> None
|
|
* ```
|
|
*/
|
|
export function lazy_or(first, second) {
|
|
if (first instanceof Some) {
|
|
return first;
|
|
} else {
|
|
return second();
|
|
}
|
|
}
|
|
|
|
function values_loop(loop$list, loop$acc) {
|
|
while (true) {
|
|
let list = loop$list;
|
|
let acc = loop$acc;
|
|
if (list instanceof $Empty) {
|
|
return reverse(acc);
|
|
} else {
|
|
let $ = list.head;
|
|
if ($ instanceof Some) {
|
|
let rest = list.tail;
|
|
let first = $[0];
|
|
loop$list = rest;
|
|
loop$acc = listPrepend(first, acc);
|
|
} else {
|
|
let rest = list.tail;
|
|
loop$list = rest;
|
|
loop$acc = acc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Given a list of `Option`s,
|
|
* returns only the values inside `Some`.
|
|
*
|
|
* ## Examples
|
|
*
|
|
* ```gleam
|
|
* values([Some(1), None, Some(3)])
|
|
* // -> [1, 3]
|
|
* ```
|
|
*/
|
|
export function values(options) {
|
|
return values_loop(options, toList([]));
|
|
}
|