diff options
-rw-r--r-- | src/gleam/atom.gleam | 10 | ||||
-rw-r--r-- | src/gleam/bool.gleam | 43 | ||||
-rw-r--r-- | src/gleam/dynamic.gleam | 75 | ||||
-rw-r--r-- | src/gleam/float.gleam | 69 | ||||
-rw-r--r-- | src/gleam/function.gleam | 2 | ||||
-rw-r--r-- | src/gleam/int.gleam | 65 | ||||
-rw-r--r-- | src/gleam/iodata.gleam | 40 | ||||
-rw-r--r-- | src/gleam/list.gleam | 2 | ||||
-rw-r--r-- | src/gleam/order.gleam | 40 | ||||
-rw-r--r-- | src/gleam/pair.gleam | 39 | ||||
-rw-r--r-- | src/gleam/result.gleam | 16 |
11 files changed, 397 insertions, 4 deletions
diff --git a/src/gleam/atom.gleam b/src/gleam/atom.gleam index e73b989..ccc7eb7 100644 --- a/src/gleam/atom.gleam +++ b/src/gleam/atom.gleam @@ -1,17 +1,27 @@ +/// A datatype and related functions for working with Erlang atoms. + pub external type Atom; +/// Error returned when a given Atom does not currently exist pub type AtomNotLoaded { AtomNotLoaded } +/// Will return a value of type `Atom` that represents a specific Erlang +/// atom from whom the string is its text representation if it exists. +/// pub external fn from_string(String) -> Result(Atom, AtomNotLoaded) = "gleam_stdlib" "atom_from_string"; /// This function can create a new atom if one does not already exist for /// the given string. Atoms are not garbage collected so this can result /// in a memory leak if called over time on new values +/// pub external fn create_from_string(String) -> Atom = "gleam_stdlib" "atom_create_from_string"; +/// Retuns a `String` corresponding to the text representation of the given +/// `Atom` +/// pub external fn to_string(Atom) -> String = "gleam_stdlib" "atom_to_string"; diff --git a/src/gleam/bool.gleam b/src/gleam/bool.gleam index 6c77e7a..76476c3 100644 --- a/src/gleam/bool.gleam +++ b/src/gleam/bool.gleam @@ -1,5 +1,14 @@ +/// A set of utility functions for working with `Bool` values. + import gleam/order.{Order} +/// Returns the opposite Bool value +/// +/// ## Examples +/// ```gleam +/// negate(True) == False +/// ``` +/// pub fn negate(bool: Bool) -> Bool { case bool { True -> False @@ -7,6 +16,14 @@ pub fn negate(bool: Bool) -> Bool { } } +/// Compares two bools and returns the first values Order to the second. +/// +/// ## Examples +/// ```gleam +/// import gleam/order +/// compare(True, False) == order.Gt +/// ``` +/// pub fn compare(a: Bool, b: Bool) -> Order { case a, b { True, True -> order.Eq @@ -16,6 +33,15 @@ pub fn compare(a: Bool, b: Bool) -> Order { } } +/// Returns `True` if either Bool value is `True`. +/// +/// ## Examples +/// ```gleam +/// max(True, False) == True +/// max(False, True) === True +/// max(False, False) === False +/// ``` +/// pub fn max(a: Bool, b: Bool) -> Bool { case a { True -> True @@ -23,6 +49,15 @@ pub fn max(a: Bool, b: Bool) -> Bool { } } +/// Returns `False` if either Bool value is `False`. +/// +/// ## Examples +/// ```gleam +/// max(True, False) == False +/// max(False, True) === False +/// max(False, False) === False +/// ``` +/// pub fn min(a: Bool, b: Bool) -> Bool { case a { False -> False @@ -30,6 +65,14 @@ pub fn min(a: Bool, b: Bool) -> Bool { } } +/// Returns a numeric representation of the value: +/// +/// ## Examples +/// ```gleam +/// to_int(True) == 1 +/// to_int(False) == 0 +/// ``` +/// pub fn to_int(bool: Bool) -> Int { case bool { False -> 0 diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index 05e523f..b080068 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -1,10 +1,11 @@ +/// `Dynamic` data is data that we don"t know the type of yet. +/// We likely get data like this from interop with Erlang, or from +/// IO with the outside world. + import gleam/list as list_mod import gleam/atom import gleam/result -/// `Dynamic` data is data that we don"t know the type of yet. -/// We likely get data like this from interop with Erlang, or from -/// IO with the outside world. pub external type Dynamic; /// Convert any Gleam data into `Dynamic` data. @@ -18,27 +19,79 @@ pub external fn from(a) -> Dynamic = "gleam_stdlib" "identity"; /// pub external fn unsafe_coerce(a) -> b = "gleam_stdlib" "identity"; +/// Safely cast a Dynamic value into a String. +/// +/// ## Examples +/// ```gleam +/// string(from("Hello")) == Ok("Hello") +/// string(from(123)) == Error("Expected a String, got `123`") +/// ``` pub external fn string(from: Dynamic) -> Result(String, String) = "gleam_stdlib" "decode_string" +/// Safely cast a Dynamic value into a String. +/// +/// ## Examples +/// ```gleam +/// int(from(123)) == Ok(123) +/// int(from("Hello")) == Error("Expected an Int, got `\"Hello World\"`") +/// ``` pub external fn int(from: Dynamic) -> Result(Int, String) = "gleam_stdlib" "decode_int" +/// Safely cast a Dynamic value into a Float. +/// +/// ## Examples +/// ```gleam +/// float(from(2.0)) == Ok(2.0) +/// float(from(123)) == Error("Expected a Float, got `123`") +/// ``` pub external fn float(from: Dynamic) -> Result(Float, String) = "gleam_stdlib" "decode_float" +/// Safely cast a Dynamic value into an Atom. +/// +/// ## Examples +/// ```gleam +/// import gleam/atom.{create_from_string, to_string} +/// to_string(atom(from(create_from_string("hello")))) == "hello" +/// atom(from(123)) == Error("Expected an Atom, got `123`") +/// ``` pub external fn atom(from: Dynamic) -> Result(atom.Atom, String) = "gleam_stdlib" "decode_atom" +/// Safely cast a Dynamic value into a Bool. +/// +/// ## Examples +/// ```gleam +/// bool(from(True)) == Ok(True) +/// bool(from(123)) == Error("Expected a Bool, got `123`") +/// ``` pub external fn bool(from: Dynamic) -> Result(Bool, String) = "gleam_stdlib" "decode_bool" +/// Safely cast a Dynamic value into a String. +/// +/// ## Examples +/// ```gleam +/// import gleam/result +/// let f = fn() { 1 } +/// result.map(thunk(from(f)), fn(v) { v == f}) == True +/// thunk(from(123)) == Error("Expected a zero arity function, got `123`") +/// ``` pub external fn thunk(from: Dynamic) -> Result(fn() -> Dynamic, String) = "gleam_stdlib" "decode_thunk" external fn list_dynamic(from: Dynamic) -> Result(List(Dynamic), String) = "gleam_stdlib" "decode_list" +/// Safely cast a Dynamic value into a List of some type. +/// +/// ## Examples +/// ```gleam +/// list(from(["a", "b", "c"]), string) == Ok(["a", "b", "c"]) +/// list(from([1, 2, 3]), string) == Error("Expected a List, got `[1, 2, 3]`") +/// ``` pub fn list( from dynamic: Dynamic, containing decoder_type: fn(Dynamic) -> Result(inner, String), @@ -48,8 +101,24 @@ pub fn list( |> result.then(_, list_mod.traverse(_, decoder_type)) } +/// Returns a field from a Dynamic value representing a map if it exists. +/// This will not succeed on a record. +/// +/// ## Examples +/// ```gleam +/// import gleam/map +/// field(from(map.new("Hello", "World")), "Hello") == Ok(Dynamic) +/// field(from(123)) == Error("Expected a map with key `\"Hello\"`, got `123`") +/// ``` pub external fn field(from: Dynamic, named: a) -> Result(Dynamic, String) = "gleam_stdlib" "decode_field" +/// Returns an element of a Dynamic value representing a tuple if it exists. +/// +/// ## Examples +/// ```gleam +/// element(from(tuple(1, 2)), 0) == Ok(Dynamic) +/// element(from(tuple(1, 2)), 2) == Error("Element position is out-of-bounds") +/// ``` pub external fn element(from: Dynamic, position: Int) -> Result(Dynamic, String) = "gleam_stdlib" "decode_element" diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam index 1eda66b..4ee941d 100644 --- a/src/gleam/float.gleam +++ b/src/gleam/float.gleam @@ -1,16 +1,42 @@ +/// A set of utility functions for working with `Float` values. + import gleam/iodata import gleam/order.{Order} import gleam/result.{Option} +/// Attempts to parse the String as a Float if possible +/// +/// ## Examples +/// ```gleam +/// parse("2.3") == Some(2.3) +/// parse("ABC") == None +/// ``` +/// pub external fn parse(String) -> Option(Float) = "gleam_stdlib" "parse_float"; +/// Returns the string representation of the provided +/// `Float` value +/// +/// ## Examples +/// ```gleam +/// to_string(2.3) == "2.3" +/// ``` +/// pub fn to_string(f: Float) -> String { f |> iodata.from_float |> iodata.to_string } + +/// Compares two `Floats`, returning an `Order` +/// +/// ## Examples +/// ```gleam +/// compare(2.0, 2.3) == Lt +/// ``` +/// pub fn compare(a: Float, b: Float) -> Order { case a == b { True -> order.Eq @@ -22,6 +48,13 @@ pub fn compare(a: Float, b: Float) -> Order { } } +/// Compares two `Floats`, returning the smaller of the two +/// +/// ## Examples +/// ```gleam +/// min(2.0, 2.3) == 2.0 +/// ``` +/// pub fn min(a: Float, b: Float) -> Float { case a <. b { True -> a @@ -29,6 +62,13 @@ pub fn min(a: Float, b: Float) -> Float { } } +/// Compares two `Floats`, returning the larger of the two +/// +/// ## Examples +/// ```gleam +/// max(2.0, 2.3) == 2.3 +/// ``` +/// pub fn max(a: Float, b: Float) -> Float { case a >. b { True -> a @@ -36,10 +76,39 @@ pub fn max(a: Float, b: Float) -> Float { } } +/// Rounds the value to the next highest whole number as a Float +/// +/// ## Examples +/// ```gleam +/// ceiling(2.3) == 3.0 +/// ``` +/// pub external fn ceiling(Float) -> Float = "math" "ceil"; +/// Rounds the value to the next lowest whole number as a Float +/// +/// ## Examples +/// ```gleam +/// floor(2.3) == 2.0 +/// ``` +/// pub external fn floor(Float) -> Float = "math" "floor"; +/// Rounds the value to the nearest whole number as an Int +/// +/// ## Examples +/// ```gleam +/// round(2.3) == 2 +/// round(2.5) == 3 +/// ``` +/// pub external fn round(Float) -> Int = "erlang" "round"; +/// Returns the value as an Int, truncating all decimal digits. +/// +/// ## Examples +/// ```gleam +/// truncate(2.4343434847383438) = 2 +/// ``` +/// pub external fn truncate(Float) -> Int = "erlang" "trunc"; diff --git a/src/gleam/function.gleam b/src/gleam/function.gleam index 6421dd1..0839def 100644 --- a/src/gleam/function.gleam +++ b/src/gleam/function.gleam @@ -1,3 +1,5 @@ +/// A set of utility higher-order functions for working with functions. + /// Takes two functions and chains them together to form one function that takes /// the input from the first and returns the output of the second. pub fn compose(fun1: fn(a) -> b, fun2: fn(b) -> c) -> fn(a) -> c { diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam index 9ff5328..bd264fd 100644 --- a/src/gleam/int.gleam +++ b/src/gleam/int.gleam @@ -1,12 +1,47 @@ +// A set of utility functions for working with `Int` values + import gleam/order.{Order} import gleam/result.{Option} +/// Attempts to parse the String as an Int if possible +/// +/// ## Examples +/// ```gleam +/// parse("2") == Some(2) +/// parse("ABC") == None +/// ``` +/// pub external fn parse(String) -> Option(Int) = "gleam_stdlib" "parse_int"; +/// Returns the string representation of the provided +/// `Int` value +/// +/// ## Examples +/// ```gleam +/// to_string(2) == "2" +/// ``` +/// pub external fn to_string(Int) -> String = "erlang" "integer_to_binary" +/// Returns the string representation of the provided +/// `Int` value in the base provided. +/// +/// ## Examples +/// ```gleam +/// to_base_string(2, 2) == "10" +/// to_base_string(48, 16) == "30" +/// to_base_string(48, 36) == "1C" +/// ``` +/// pub external fn to_base_string(Int, Int) -> String = "erlang" "integer_to_binary" +/// Compares two `Int`, returning an `Order` +/// +/// ## Examples +/// ```gleam +/// compare(2, 3) == Lt +/// ``` +/// pub fn compare(a: Int, b: Int) -> Order { case a == b { True -> order.Eq @@ -18,6 +53,13 @@ pub fn compare(a: Int, b: Int) -> Order { } } +/// Compares two `Int`, returning the smaller of the two +/// +/// ## Examples +/// ```gleam +/// min(2, 3) == 2 +/// ``` +/// pub fn min(a: Int, b: Int) -> Int { case a < b { True -> a @@ -25,6 +67,13 @@ pub fn min(a: Int, b: Int) -> Int { } } +/// Compares two `Int`, returning the larger of the two +/// +/// ## Examples +/// ```gleam +/// max(2, 3) == 3 +/// ``` +/// pub fn max(a: Int, b: Int) -> Int { case a > b { True -> a @@ -32,10 +81,26 @@ pub fn max(a: Int, b: Int) -> Int { } } +/// Returns whether the value provided is even +/// +/// ## Examples +/// ```gleam +/// is_even(2) == True +/// is_even(3) == False +/// ``` +/// pub fn is_even(x: Int) -> Bool { x % 2 == 0 } +/// Returns whether the value provided is odd +/// +/// ## Examples +/// ```gleam +/// is_odd(3) == True +/// is_odd(2) == False +/// ``` +/// pub fn is_odd(x: Int) -> Bool { x % 2 != 0 } diff --git a/src/gleam/iodata.gleam b/src/gleam/iodata.gleam index 821581e..f34b40f 100644 --- a/src/gleam/iodata.gleam +++ b/src/gleam/iodata.gleam @@ -1,39 +1,71 @@ +/// Represents Erlang's `iodata` type and the associated functions +/// to work with it. + pub external type Iodata; +/// Prepends the string `prefix` to `to` +/// pub external fn prepend(to: Iodata, prefix: String) -> Iodata = "gleam_stdlib" "iodata_prepend"; +/// Appends the string `suffix` to `to` +/// pub external fn append(to: Iodata, suffix: String) -> Iodata = "gleam_stdlib" "iodata_append"; +/// Prepends the Iodata `prefix` to `to` +/// pub external fn prepend_iodata(to: Iodata, prefix: Iodata) -> Iodata = "gleam_stdlib" "iodata_prepend"; +/// Prepends the Iodata `prefix` to `to` +/// pub external fn append_iodata(to: Iodata, suffix: Iodata) -> Iodata = "gleam_stdlib" "iodata_append"; +/// Builds an Iodata value from the supplied list of strings +/// pub external fn from_strings(List(String)) -> Iodata = "gleam_stdlib" "identity"; +/// Builds a new Iodata out of a list of Iodata +/// pub external fn concat(List(Iodata)) -> Iodata = "gleam_stdlib" "identity"; +/// Turns a `String` into an `Iodata` +/// pub external fn new(String) -> Iodata = "gleam_stdlib" "identity"; +/// Turns an `Iodata` into a `String` +/// pub external fn to_string(Iodata) -> String = "erlang" "iolist_to_binary"; +/// Returns the size of the Iodata in bytes +/// pub external fn byte_size(Iodata) -> Int = "erlang" "iolist_size"; +/// Creates an `Iodata` value from a `Float` value. +/// pub external fn from_float(Float) -> Iodata = "io_lib_format" "fwrite_g"; +/// Converts Iodata to a new Iodata where valid UTF-8 string data is +/// lowercased +/// pub external fn lowercase(Iodata) -> Iodata = "string" "lowercase" +/// Converts Iodata to a new Iodata where valid UTF-8 string data is +/// uppercased +/// pub external fn uppercase(Iodata) -> Iodata = "string" "uppercase" +/// Converts Iodata to a new Iodata where valid UTF-8 string data is +/// reversed +/// pub external fn reverse(Iodata) -> Iodata = "string" "reverse" type Direction { @@ -43,6 +75,8 @@ type Direction { external fn erl_split(Iodata, String, Direction) -> List(Iodata) = "string" "split" +/// Splits the supplied Iodata by the pattern `on` +/// pub fn split(iodata: Iodata, on pattern: String) -> List(Iodata) { erl_split(iodata, pattern, All) } @@ -50,6 +84,8 @@ pub fn split(iodata: Iodata, on pattern: String) -> List(Iodata) { external fn erl_replace(Iodata, String, String, Direction) -> Iodata = "string" "replace" +/// Replaces all instances of `all` with the string `with` +/// pub fn replace( in iodata: Iodata, each pattern: String, @@ -58,6 +94,10 @@ pub fn replace( erl_replace(iodata, pattern, substitute, All) } +/// Prepends the string `prefix` to `to` +/// pub external fn is_equal(Iodata, Iodata) -> Bool = "string" "equal" +/// Prepends the string `prefix` to `to` +/// pub external fn is_empty(Iodata) -> Bool = "string" "is_empty" diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam index 86e88ea..4b832bc 100644 --- a/src/gleam/list.gleam +++ b/src/gleam/list.gleam @@ -8,9 +8,11 @@ pub type LengthMismatch { } /// Using the Erlang C BIF implementation. +/// pub external fn length(List(a)) -> Int = "erlang" "length" /// Using the Erlang C BIF implementation. +/// pub external fn reverse(List(a)) -> List(a) = "lists" "reverse" pub fn is_empty(list: List(a)) -> Bool { diff --git a/src/gleam/order.gleam b/src/gleam/order.gleam index 1c5a417..4b12af7 100644 --- a/src/gleam/order.gleam +++ b/src/gleam/order.gleam @@ -1,9 +1,19 @@ +/// Represents the result of a single comparison to determine the precise +/// ordering of two values. + pub type Order { Lt Eq Gt } +/// Switches the evaluated ordering from one direction to the other +/// +/// ## Examples +/// ```gleam +/// reverse(Lt) == Gt +/// ``` +/// pub fn reverse(order: Order) -> Order { case order { Lt -> Gt @@ -12,6 +22,13 @@ pub fn reverse(order: Order) -> Order { } } +/// Produces a numeric representation of the order +/// +/// ## Examples +/// ```gleam +/// to_int(Lt) == -1 +/// ``` +/// pub fn to_int(order: Order) -> Int { case order { Lt -> -1 @@ -20,7 +37,14 @@ pub fn to_int(order: Order) -> Int { } } -pub fn compare(a: Order, b: Order) -> Order { +/// Compares two Order values to one another, producing a new Order +/// +/// ## Examples +/// ```gleam +/// compare(Eq, to: Lt) == Gt +/// ``` +/// +pub fn compare(a: Order, to b: Order) -> Order { case a, b { x, y if x == y -> Eq Lt, _ | Eq, Gt -> Lt @@ -28,6 +52,13 @@ pub fn compare(a: Order, b: Order) -> Order { } } +/// Returns the highest of two orders +/// +/// ## Examples +/// ```gleam +/// max(Eq, Lt) == Eq +/// ``` +/// pub fn max(a: Order, b: Order) -> Order { case a, b { Gt, _ -> Gt @@ -36,6 +67,13 @@ pub fn max(a: Order, b: Order) -> Order { } } +/// Returns the lowest of two orders +/// +/// ## Examples +/// ```gleam +/// min(Eq, Lt) == Lt +/// ``` +/// pub fn min(a: Order, b: Order) -> Order { case a, b { Lt, _ -> Lt diff --git a/src/gleam/pair.gleam b/src/gleam/pair.gleam index 4cbce53..64b4212 100644 --- a/src/gleam/pair.gleam +++ b/src/gleam/pair.gleam @@ -1,23 +1,62 @@ +// A set of utility functions for working with 2-tuples, or pairs. + +/// Returns the first element in a pair. +/// +/// ## Examples +/// ```gleam +/// first(tuple(1, 2)) = 1 +/// ``` +/// pub fn first(pair: tuple(a, b)) -> a { let tuple(a, _) = pair a } +/// Returns the second element in a pair. +/// +/// ## Examples +/// ```gleam +/// second(tuple(1, 2)) = 2 +/// ``` +/// pub fn second(pair: tuple(a, b)) -> b { let tuple(_, a) = pair a } +/// Returns a new pair with the elements swapped. +/// +/// ## Examples +/// ```gleam +/// swap(tuple(1, 2)) = tuple(2, 1) +/// ``` +/// pub fn swap(pair: tuple(a, b)) -> tuple(b, a) { let tuple(a, b) = pair tuple(b, a) } +/// Returns a new pair with the first element having had `with` applied to +/// it. +/// +/// ## Examples +/// ```gleam +/// map_first(tuple(1, 2), fn(n) { n * 2 }) = 2 +/// ``` +/// pub fn map_first(of pair: tuple(a, b), with fun: fn(a) -> c) -> tuple(c, b) { let tuple(a, b) = pair tuple(fun(a), b) } +/// Returns a new pair with the second element having had `with` applied to +/// it. +/// +/// ## Examples +/// ```gleam +/// map_second(tuple(1, 2), fn(n) { n * 2 }) = 4 +/// ``` +/// pub fn map_second(of pair: tuple(a, b), with fun: fn(b) -> c) -> tuple(a, c) { let tuple(a, b) = pair tuple(a, fun(b)) diff --git a/src/gleam/result.gleam b/src/gleam/result.gleam index 1aa7ff5..5b3170d 100644 --- a/src/gleam/result.gleam +++ b/src/gleam/result.gleam @@ -1,6 +1,8 @@ /// Result represents the result of something that may succeed or fail. /// `Ok` means it was successful, `Error` means it failed. +/// Returns whether the value is Ok +/// pub fn is_ok(result: Result(a, e)) -> Bool { case result { Error(_) -> False @@ -8,6 +10,7 @@ pub fn is_ok(result: Result(a, e)) -> Bool { } } +/// Returns whether the value is Error pub fn is_error(result: Result(a, e)) -> Bool { case result { Ok(_) -> False @@ -15,6 +18,9 @@ pub fn is_error(result: Result(a, e)) -> Bool { } } +/// Executes the function `with` on inner value when Result is Ok, will noop +/// if it is Error +/// pub fn map( over result: Result(a, e), with fun: fn(a) -> b, @@ -25,6 +31,9 @@ pub fn map( } } +/// Will execute the function `with` on inner value when Result is Err, will noop +/// if it is Ok +/// pub fn map_error( over result: Result(a, e), with fun: fn(e) -> f, @@ -35,6 +44,8 @@ pub fn map_error( } } +/// Will unnest the inner value of a result nested within another result +/// pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) { case result { Ok(x) -> x @@ -42,6 +53,8 @@ pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) { } } +/// An alias of `map` +/// pub fn then( result: Result(a, e), apply fun: fn(a) -> Result(b, e), @@ -52,6 +65,9 @@ pub fn then( } } +/// Will return the inner value of a Ok value. If an error, will +/// return the value provided as `or` +/// pub fn unwrap(result: Result(a, e), or default: a) -> a { case result { Ok(v) -> v |