aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2021-07-13 10:23:17 +0100
committerLouis Pilfold <louis@lpil.uk>2021-07-13 11:06:58 +0100
commitfa93398d805ba13a44d26b4ccb83ef3f9edf1d01 (patch)
treefd12db4417937e42232cb8db43e2fd0f5b875324
parent3e07ebbc721bd55d111c4e48af76dc8243e0149b (diff)
downloadgleam_stdlib-fa93398d805ba13a44d26b4ccb83ef3f9edf1d01.tar.gz
gleam_stdlib-fa93398d805ba13a44d26b4ccb83ef3f9edf1d01.zip
JavaScript test runner
-rw-r--r--bin/run-tests.js38
-rw-r--r--bin/test.sh7
-rw-r--r--package.json6
-rw-r--r--src/gleam/atom.gleam118
-rw-r--r--src/gleam/base.gleam66
-rw-r--r--src/gleam/bit_builder.gleam183
-rw-r--r--src/gleam/bit_string.gleam126
-rw-r--r--src/gleam/bool.gleam372
-rw-r--r--src/gleam/dynamic.gleam1259
-rw-r--r--src/gleam/float.gleam422
-rw-r--r--src/gleam/function.gleam122
-rw-r--r--src/gleam/int.gleam408
-rw-r--r--src/gleam/io.gleam140
-rw-r--r--src/gleam/iterator.gleam1822
-rw-r--r--src/gleam/list.gleam2810
-rw-r--r--src/gleam/map.gleam594
-rw-r--r--src/gleam/option.gleam412
-rw-r--r--src/gleam/order.gleam178
-rw-r--r--src/gleam/os.gleam107
-rw-r--r--src/gleam/pair.gleam114
-rw-r--r--src/gleam/queue.gleam472
-rw-r--r--src/gleam/regex.gleam220
-rw-r--r--src/gleam/result.gleam508
-rw-r--r--src/gleam/set.gleam390
-rw-r--r--src/gleam/should.gleam54
-rw-r--r--src/gleam/string.gleam892
-rw-r--r--src/gleam/string_builder.gleam336
-rw-r--r--src/gleam/uri.gleam626
-rw-r--r--src/gleam_stdlib.erl16
-rw-r--r--src/gleam_stdlib.js0
-rw-r--r--test/gleam/atom_test.gleam90
-rw-r--r--test/gleam/base_test.gleam192
-rw-r--r--test/gleam/bit_builder_test.gleam126
-rw-r--r--test/gleam/bit_string_test.gleam189
-rw-r--r--test/gleam/bool_test.gleam170
-rw-r--r--test/gleam/dynamic_test.gleam1488
-rw-r--r--test/gleam/float_test.gleam446
-rw-r--r--test/gleam/function_test.gleam206
-rw-r--r--test/gleam/int_test.gleam338
-rw-r--r--test/gleam/iterator_test.gleam706
-rw-r--r--test/gleam/list_test.gleam1144
-rw-r--r--test/gleam/map_test.gleam278
-rw-r--r--test/gleam/option_test.gleam230
-rw-r--r--test/gleam/order_test.gleam156
-rw-r--r--test/gleam/os_test.gleam80
-rw-r--r--test/gleam/pair_test.gleam116
-rw-r--r--test/gleam/queue_test.gleam534
-rw-r--r--test/gleam/regex_test.gleam120
-rw-r--r--test/gleam/result_test.gleam338
-rw-r--r--test/gleam/set_test.gleam160
-rw-r--r--test/gleam/string_builder_test.gleam204
-rw-r--r--test/gleam/string_test.gleam664
-rw-r--r--test/gleam/uri_test.gleam586
53 files changed, 10796 insertions, 10583 deletions
diff --git a/bin/run-tests.js b/bin/run-tests.js
new file mode 100644
index 0000000..46e7963
--- /dev/null
+++ b/bin/run-tests.js
@@ -0,0 +1,38 @@
+import { opendir } from "fs/promises";
+
+const dir = "gen/javascript/gleam/";
+
+async function main() {
+ console.log("Running tests...");
+
+ let passes = 0;
+ let failures = 0;
+
+ for await (let entry of await opendir(dir)) {
+ if (!entry.name.endsWith("_test.js")) continue;
+ let path = "../" + dir + entry.name;
+ process.stdout.write("\ngleam/" + entry.name.slice(0, -3) + ":\n ");
+ let module = await import(path);
+
+ for (let fnName of Object.keys(module)) {
+ if (!fnName.endsWith("_test")) continue;
+ try {
+ module[fnName]();
+ process.stdout.write("✨");
+ passes++;
+ } catch (error) {
+ process.stdout.write(`❌ ${fnName}: ${error}\n `);
+ failures++;
+ }
+ }
+ }
+
+ console.log(`
+
+${passes + failures} tests
+${passes} passes
+${failures} failures`);
+ process.exit(failures ? 1 : 0);
+}
+
+main();
diff --git a/bin/test.sh b/bin/test.sh
new file mode 100644
index 0000000..777c50b
--- /dev/null
+++ b/bin/test.sh
@@ -0,0 +1,7 @@
+set -eu
+
+OUT=gen/javascript
+rm -fr $OUT
+gleam compile-package --name gleam_stdlib --target javascript --src src --test test --out $OUT
+cp src/*.js $OUT/
+node bin/run-tests.js
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0e087bf
--- /dev/null
+++ b/package.json
@@ -0,0 +1,6 @@
+{
+ "type": "module",
+ "scripts": {
+ "test": "sh bin/test.sh"
+ }
+}
diff --git a/src/gleam/atom.gleam b/src/gleam/atom.gleam
index e85f5d5..2d96053 100644
--- a/src/gleam/atom.gleam
+++ b/src/gleam/atom.gleam
@@ -1,62 +1,64 @@
-/// Atom is a special string-like data-type that is most commonly used for
-/// interfacing with code written in other BEAM languages such as Erlang and
-/// Elixir. It is preferable to define your own custom types to use instead of
-/// atoms where possible.
-///
-/// Atoms are not used much in typical Gleam code!
-///
-/// ## Creating atoms
-///
-/// We can create atoms with the the [`create_from_string`](#create_from_string)
-/// function, though we must be careful when doing so as atoms are never
-/// garbage collected. If we create too many atoms (for example, if we convert
-/// user input into atoms) we may hit the max limit of atoms and cause the
-/// virtual machine to crash.
-///
-pub external type Atom
+if erlang {
+ /// Atom is a special string-like data-type that is most commonly used for
+ /// interfacing with code written in other BEAM languages such as Erlang and
+ /// Elixir. It is preferable to define your own custom types to use instead of
+ /// atoms where possible.
+ ///
+ /// Atoms are not used much in typical Gleam code!
+ ///
+ /// ## Creating atoms
+ ///
+ /// We can create atoms with the the [`create_from_string`](#create_from_string)
+ /// function, though we must be careful when doing so as atoms are never
+ /// garbage collected. If we create too many atoms (for example, if we convert
+ /// user input into atoms) we may hit the max limit of atoms and cause the
+ /// virtual machine to crash.
+ ///
+ pub external type Atom
-/// An error returned when no atom is found in the virtual machine's atom table
-/// for a given string when calling the [`from_string`](#from_string) function.
-pub type FromStringError {
- AtomNotLoaded
-}
+ /// An error returned when no atom is found in the virtual machine's atom table
+ /// for a given string when calling the [`from_string`](#from_string) function.
+ pub type FromStringError {
+ AtomNotLoaded
+ }
-/// Finds an existing Atom for the given String.
-///
-/// If no atom is found in the virtual machine's atom table for the String then
-/// an error is returned.
-///
-/// ## Examples
-///
-/// > from_string("ok")
-/// Ok(create_from_string("ok"))
-///
-/// > from_string("some_new_atom")
-/// Error(AtomNotLoaded)
-///
-pub external fn from_string(String) -> Result(Atom, FromStringError) =
- "gleam_stdlib" "atom_from_string"
+ /// Finds an existing Atom for the given String.
+ ///
+ /// If no atom is found in the virtual machine's atom table for the String then
+ /// an error is returned.
+ ///
+ /// ## Examples
+ ///
+ /// > from_string("ok")
+ /// Ok(create_from_string("ok"))
+ ///
+ /// > from_string("some_new_atom")
+ /// Error(AtomNotLoaded)
+ ///
+ pub external fn from_string(String) -> Result(Atom, FromStringError) =
+ "gleam_stdlib" "atom_from_string"
-/// Creates an atom from a string, inserting a new value into the virtual
-/// machine's atom table if an atom does not already exist for the given
-/// string.
-///
-/// We must be careful when using this function as there is a limit to the
-/// number of atom that can fit in the virtual machine's atom table. Never
-/// convert user input into atoms as filling the atom table will cause the
-/// virtual machine to crash!
-///
-pub external fn create_from_string(String) -> Atom =
- "gleam_stdlib" "atom_create_from_string"
+ /// Creates an atom from a string, inserting a new value into the virtual
+ /// machine's atom table if an atom does not already exist for the given
+ /// string.
+ ///
+ /// We must be careful when using this function as there is a limit to the
+ /// number of atom that can fit in the virtual machine's atom table. Never
+ /// convert user input into atoms as filling the atom table will cause the
+ /// virtual machine to crash!
+ ///
+ 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`.
-///
-/// ## Examples
-///
-/// > let ok_atom = create_from_string("ok")
-/// > to_string(ok_atom)
-/// "ok"
-///
-pub external fn to_string(Atom) -> String =
- "gleam_stdlib" "atom_to_string"
+ /// Retuns a `String` corresponding to the text representation of the given
+ /// `Atom`.
+ ///
+ /// ## Examples
+ ///
+ /// > let ok_atom = create_from_string("ok")
+ /// > to_string(ok_atom)
+ /// "ok"
+ ///
+ pub external fn to_string(Atom) -> String =
+ "gleam_stdlib" "atom_to_string"
+}
diff --git a/src/gleam/base.gleam b/src/gleam/base.gleam
index c1c3824..5ca741e 100644
--- a/src/gleam/base.gleam
+++ b/src/gleam/base.gleam
@@ -1,41 +1,43 @@
-import gleam/bit_string.{BitString}
-import gleam/string
+if erlang {
+ import gleam/bit_string.{BitString}
+ import gleam/string
-external fn erl_encode64(BitString) -> String =
- "base64" "encode"
+ external fn erl_encode64(BitString) -> String =
+ "base64" "encode"
-external fn erl_decode64(String) -> Result(BitString, Nil) =
- "gleam_stdlib" "base_decode64"
+ external fn erl_decode64(String) -> Result(BitString, Nil) =
+ "gleam_stdlib" "base_decode64"
-/// Encodes a BitString into a base 64 encoded string.
-pub fn encode64(input: BitString, padding: Bool) -> String {
- let encoded = erl_encode64(input)
- case padding {
- True -> encoded
- False -> string.replace(encoded, "=", "")
+ /// Encodes a BitString into a base 64 encoded string.
+ pub fn encode64(input: BitString, padding: Bool) -> String {
+ let encoded = erl_encode64(input)
+ case padding {
+ True -> encoded
+ False -> string.replace(encoded, "=", "")
+ }
}
-}
-/// Decodes a base 64 encoded string into a BitString.
-pub fn decode64(encoded: String) -> Result(BitString, Nil) {
- let padded = case bit_string.byte_size(bit_string.from_string(encoded)) % 4 {
- 0 -> encoded
- n -> string.append(encoded, string.repeat("=", 4 - n))
+ /// Decodes a base 64 encoded string into a BitString.
+ pub fn decode64(encoded: String) -> Result(BitString, Nil) {
+ let padded = case bit_string.byte_size(bit_string.from_string(encoded)) % 4 {
+ 0 -> encoded
+ n -> string.append(encoded, string.repeat("=", 4 - n))
+ }
+ erl_decode64(padded)
}
- erl_decode64(padded)
-}
-/// Encodes a BitString into a base 64 encoded string with URL and filename safe alphabet.
-pub fn url_encode64(input: BitString, padding: Bool) -> String {
- encode64(input, padding)
- |> string.replace("+", "-")
- |> string.replace("/", "_")
-}
+ /// Encodes a BitString into a base 64 encoded string with URL and filename safe alphabet.
+ pub fn url_encode64(input: BitString, padding: Bool) -> String {
+ encode64(input, padding)
+ |> string.replace("+", "-")
+ |> string.replace("/", "_")
+ }
-/// Decodes a base 64 encoded string with URL and filename safe alphabet into a BitString.
-pub fn url_decode64(encoded: String) -> Result(BitString, Nil) {
- encoded
- |> string.replace("-", "+")
- |> string.replace("_", "/")
- |> decode64()
+ /// Decodes a base 64 encoded string with URL and filename safe alphabet into a BitString.
+ pub fn url_decode64(encoded: String) -> Result(BitString, Nil) {
+ encoded
+ |> string.replace("-", "+")
+ |> string.replace("_", "/")
+ |> decode64()
+ }
}
diff --git a/src/gleam/bit_builder.gleam b/src/gleam/bit_builder.gleam
index d69fea5..738c79c 100644
--- a/src/gleam/bit_builder.gleam
+++ b/src/gleam/bit_builder.gleam
@@ -1,102 +1,107 @@
-import gleam/bit_string.{BitString}
-import gleam/string_builder.{StringBuilder}
+if erlang {
+ import gleam/bit_string.{BitString}
+ import gleam/string_builder.{StringBuilder}
-/// BitBuilder is a type used for efficiently concatenating bits to create bit
-/// strings.
-///
-/// If we append one bit string to another the bit strings must be copied to a
-/// new location in memory so that they can sit together. This behaviour
-/// enables efficient reading of the string but copying can be expensive,
-/// especially if we want to join many bit strings together.
-///
-/// BitBuilder is different in that it can be joined together in constant
-/// time using minimal memory, and then can be efficiently converted to a
-/// bit string using the `to_bit_string` function.
-///
-pub external type BitBuilder
+ /// BitBuilder is a type used for efficiently concatenating bits to create bit
+ /// strings.
+ ///
+ /// If we append one bit string to another the bit strings must be copied to a
+ /// new location in memory so that they can sit together. This behaviour
+ /// enables efficient reading of the string but copying can be expensive,
+ /// especially if we want to join many bit strings together.
+ ///
+ /// BitBuilder is different in that it can be joined together in constant
+ /// time using minimal memory, and then can be efficiently converted to a
+ /// bit string using the `to_bit_string` function.
+ ///
+ pub external type BitBuilder
-/// Prepends a bit string to the start of a builder.
-///
-/// Runs in constant time.
-///
-pub external fn prepend(to: BitBuilder, prefix: BitString) -> BitBuilder =
- "gleam_stdlib" "iodata_prepend"
+ /// Prepends a bit string to the start of a builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn prepend(to: BitBuilder, prefix: BitString) -> BitBuilder =
+ "gleam_stdlib" "iodata_prepend"
-/// Appends a bit string to the end of a builder.
-///
-/// Runs in constant time.
-///
-pub external fn append(to: BitBuilder, suffix: BitString) -> BitBuilder =
- "gleam_stdlib" "iodata_append"
+ /// Appends a bit string to the end of a builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn append(to: BitBuilder, suffix: BitString) -> BitBuilder =
+ "gleam_stdlib" "iodata_append"
-/// Prepends a builder onto the start of another.
-///
-/// Runs in constant time.
-///
-pub external fn prepend_builder(
- to: BitBuilder,
- prefix: BitBuilder,
-) -> BitBuilder =
- "gleam_stdlib" "iodata_prepend"
+ /// Prepends a builder onto the start of another.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn prepend_builder(
+ to: BitBuilder,
+ prefix: BitBuilder,
+ ) -> BitBuilder =
+ "gleam_stdlib" "iodata_prepend"
-/// Appends a builder onto the end of another.
-///
-/// Runs in constant time.
-///
-pub external fn append_builder(to: BitBuilder, suffix: BitBuilder) -> BitBuilder =
- "gleam_stdlib" "iodata_append"
+ /// Appends a builder onto the end of another.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn append_builder(
+ to: BitBuilder,
+ suffix: BitBuilder,
+ ) -> BitBuilder =
+ "gleam_stdlib" "iodata_append"
-/// Prepends a string onto the start of a builder.
-///
-/// Runs in constant time.
-///
-pub external fn prepend_string(to: BitBuilder, prefix: String) -> BitBuilder =
- "gleam_stdlib" "iodata_prepend"
+ /// Prepends a string onto the start of a builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn prepend_string(to: BitBuilder, prefix: String) -> BitBuilder =
+ "gleam_stdlib" "iodata_prepend"
-/// Appends a string onto the end of a builder.
-///
-/// Runs in constant time.
-///
-pub external fn append_string(to: BitBuilder, suffix: String) -> BitBuilder =
- "gleam_stdlib" "iodata_append"
+ /// Appends a string onto the end of a builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn append_string(to: BitBuilder, suffix: String) -> BitBuilder =
+ "gleam_stdlib" "iodata_append"
-/// Joins a list of builders into a single builders.
-///
-/// Runs in constant time.
-///
-pub external fn concat(List(BitBuilder)) -> BitBuilder =
- "gleam_stdlib" "identity"
+ /// Joins a list of builders into a single builders.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn concat(List(BitBuilder)) -> BitBuilder =
+ "gleam_stdlib" "identity"
-/// Creates a new builder from a string.
-///
-/// Runs in constant time.
-///
-pub external fn from_string(String) -> BitBuilder =
- "gleam_stdlib" "wrap_list"
+ /// Creates a new builder from a string.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn from_string(String) -> BitBuilder =
+ "gleam_stdlib" "wrap_list"
-/// Creates a new builder from a string builder.
-///
-/// Runs in constant time.
-///
-pub external fn from_string_builder(StringBuilder) -> BitBuilder =
- "gleam_stdlib" "identity"
+ /// Creates a new builder from a string builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn from_string_builder(StringBuilder) -> BitBuilder =
+ "gleam_stdlib" "identity"
-/// Creates a new builder from a bit string.
-///
-/// Runs in constant time.
-///
-pub external fn from_bit_string(BitString) -> BitBuilder =
- "gleam_stdlib" "wrap_list"
+ /// Creates a new builder from a bit string.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn from_bit_string(BitString) -> BitBuilder =
+ "gleam_stdlib" "wrap_list"
-/// Turns an builder into a bit string.
-///
-/// This function is implemented natively by the virtual machine and is highly
-/// optimised.
-///
-pub external fn to_bit_string(BitBuilder) -> BitString =
- "erlang" "list_to_bitstring"
+ /// Turns an builder into a bit string.
+ ///
+ /// This function is implemented natively by the virtual machine and is highly
+ /// optimised.
+ ///
+ pub external fn to_bit_string(BitBuilder) -> BitString =
+ "erlang" "list_to_bitstring"
-/// Returns the size of the builder's content in bytes.
-///
-pub external fn byte_size(BitBuilder) -> Int =
- "erlang" "iolist_size"
+ /// Returns the size of the builder's content in bytes.
+ ///
+ pub external fn byte_size(BitBuilder) -> Int =
+ "erlang" "iolist_size"
+}
diff --git a/src/gleam/bit_string.gleam b/src/gleam/bit_string.gleam
index 4e10268..835ff7c 100644
--- a/src/gleam/bit_string.gleam
+++ b/src/gleam/bit_string.gleam
@@ -2,77 +2,79 @@
//// The BitString type should be used instead of a String type when not utf8
//// encoded.
-pub type BitString =
- BitString
+if erlang {
+ pub type BitString =
+ BitString
-/// Converts a UTF-8 String type into a raw BitString type.
-///
-pub external fn from_string(String) -> BitString =
- "gleam_stdlib" "identity"
+ /// Converts a UTF-8 String type into a raw BitString type.
+ ///
+ pub external fn from_string(String) -> BitString =
+ "gleam_stdlib" "identity"
-/// Returns an integer which is the number of bytes in the bit string.
-///
-pub external fn byte_size(BitString) -> Int =
- "erlang" "byte_size"
+ /// Returns an integer which is the number of bytes in the bit string.
+ ///
+ pub external fn byte_size(BitString) -> Int =
+ "erlang" "byte_size"
-/// Creates a new bit string by joining two binaries.
-///
-/// ## Examples
-///
-/// > append(to: from_string("butter"), suffix: from_string("fly"))
-/// from_string("butterfly")
-///
-pub external fn append(first: BitString, second: BitString) -> BitString =
- "gleam_stdlib" "bit_string_append"
+ /// Creates a new bit string by joining two binaries.
+ ///
+ /// ## Examples
+ ///
+ /// > append(to: from_string("butter"), suffix: from_string("fly"))
+ /// from_string("butterfly")
+ ///
+ pub external fn append(first: BitString, second: BitString) -> BitString =
+ "gleam_stdlib" "bit_string_append"
-/// Extracts part of a bit string.
-///
-/// BitString part will start at given position and continue up to specified
-/// length.
-/// A negative length can be used to extract bytes at the end of a bit string.
-///
-pub external fn part(
- string: BitString,
- position: Int,
- length: Int,
-) -> Result(BitString, Nil) =
- "gleam_stdlib" "bit_string_part_"
+ /// Extracts part of a bit string.
+ ///
+ /// BitString part will start at given position and continue up to specified
+ /// length.
+ /// A negative length can be used to extract bytes at the end of a bit string.
+ ///
+ pub external fn part(
+ string: BitString,
+ position: Int,
+ length: Int,
+ ) -> Result(BitString, Nil) =
+ "gleam_stdlib" "bit_string_part_"
-/// Converts an integer to unsigned 32 bits.
-///
-/// Returns an error if integer is less than zero or equal to or larger than
-/// 2^32.
-///
-pub external fn int_to_u32(Int) -> Result(BitString, Nil) =
- "gleam_stdlib" "bit_string_int_to_u32"
+ /// Converts an integer to unsigned 32 bits.
+ ///
+ /// Returns an error if integer is less than zero or equal to or larger than
+ /// 2^32.
+ ///
+ pub external fn int_to_u32(Int) -> Result(BitString, Nil) =
+ "gleam_stdlib" "bit_string_int_to_u32"
-/// Converts unsigned 32 bits to an integer.
-///
-/// Returns an error if the bit string is not 32 bits in length.
-///
-pub external fn int_from_u32(BitString) -> Result(Int, Nil) =
- "gleam_stdlib" "bit_string_int_from_u32"
+ /// Converts unsigned 32 bits to an integer.
+ ///
+ /// Returns an error if the bit string is not 32 bits in length.
+ ///
+ pub external fn int_from_u32(BitString) -> Result(Int, Nil) =
+ "gleam_stdlib" "bit_string_int_from_u32"
-/// Tests to see whether a bit string is valid UTF-8.
-///
-pub fn is_utf8(bits: BitString) -> Bool {
- case bits {
- <<>> -> True
- <<_:utf8, rest:binary>> -> is_utf8(rest)
- _ -> False
+ /// Tests to see whether a bit string is valid UTF-8.
+ ///
+ pub fn is_utf8(bits: BitString) -> Bool {
+ case bits {
+ <<>> -> True
+ <<_:utf8, rest:binary>> -> is_utf8(rest)
+ _ -> False
+ }
}
-}
-external fn unsafe_to_string(BitString) -> String =
- "gleam_stdlib" "identity"
+ external fn unsafe_to_string(BitString) -> String =
+ "gleam_stdlib" "identity"
-/// Converts a bit string to a string.
-///
-/// Returns an error if the bit string is invalid UTF-8 data.
-///
-pub fn to_string(bits: BitString) -> Result(String, Nil) {
- case is_utf8(bits) {
- True -> Ok(unsafe_to_string(bits))
- False -> Error(Nil)
+ /// Converts a bit string to a string.
+ ///
+ /// Returns an error if the bit string is invalid UTF-8 data.
+ ///
+ pub fn to_string(bits: BitString) -> Result(String, Nil) {
+ case is_utf8(bits) {
+ True -> Ok(unsafe_to_string(bits))
+ False -> Error(Nil)
+ }
}
}
diff --git a/src/gleam/bool.gleam b/src/gleam/bool.gleam
index 684aa2f..e25f7b5 100644
--- a/src/gleam/bool.gleam
+++ b/src/gleam/bool.gleam
@@ -1,205 +1,207 @@
-import gleam/order.{Order}
+if erlang {
+ import gleam/order.{Order}
-/// A type with two possible values, True and False. Used to indicate whether
-/// things are... true or false!
-///
-/// Often is it clearer and offers more type safety to define a custom type
-/// than to use Bool. For example, rather than having a `is_teacher: Bool`
-/// field consider having a `role: SchoolRole` field where SchoolRole is a custom
-/// type that can be either Student or Teacher.
-///
-pub type Bool =
- Bool
+ /// A type with two possible values, True and False. Used to indicate whether
+ /// things are... true or false!
+ ///
+ /// Often is it clearer and offers more type safety to define a custom type
+ /// than to use Bool. For example, rather than having a `is_teacher: Bool`
+ /// field consider having a `role: SchoolRole` field where SchoolRole is a custom
+ /// type that can be either Student or Teacher.
+ ///
+ pub type Bool =
+ Bool
-/// Returns the opposite bool value.
-///
-/// This is the same as the `!` or `not` operators in some other languages.
-///
-/// ## Examples
-///
-/// > negate(True)
-/// False
-///
-/// > negate(False)
-/// True
-///
-pub fn negate(bool: Bool) -> Bool {
- case bool {
- True -> False
- False -> True
+ /// Returns the opposite bool value.
+ ///
+ /// This is the same as the `!` or `not` operators in some other languages.
+ ///
+ /// ## Examples
+ ///
+ /// > negate(True)
+ /// False
+ ///
+ /// > negate(False)
+ /// True
+ ///
+ pub fn negate(bool: Bool) -> Bool {
+ case bool {
+ True -> False
+ False -> True
+ }
}
-}
-/// Returns the nor of two bools
-///
-/// ## Examples
-///
-/// > nor(False, False)
-/// True
-///
-/// > nor(False, True)
-/// False
-///
-/// > nor(True, False)
-/// False
-///
-/// > nor(True, True)
-/// False
-///
-pub fn nor(a: Bool, b: Bool) -> Bool {
- case a, b {
- False, False -> True
- False, True -> False
- True, False -> False
- True, True -> False
+ /// Returns the nor of two bools
+ ///
+ /// ## Examples
+ ///
+ /// > nor(False, False)
+ /// True
+ ///
+ /// > nor(False, True)
+ /// False
+ ///
+ /// > nor(True, False)
+ /// False
+ ///
+ /// > nor(True, True)
+ /// False
+ ///
+ pub fn nor(a: Bool, b: Bool) -> Bool {
+ case a, b {
+ False, False -> True
+ False, True -> False
+ True, False -> False
+ True, True -> False
+ }
}
-}
-/// Returns the nand of two bools
-///
-/// ## Examples
-///
-/// > nand(False, False)
-/// True
-///
-/// > nand(False, True)
-/// True
-///
-/// > nand(True, False)
-/// True
-///
-/// > nand(True, True)
-/// False
-///
-pub fn nand(a: Bool, b: Bool) -> Bool {
- case a, b {
- False, False -> True
- False, True -> True
- True, False -> True
- True, True -> False
+ /// Returns the nand of two bools
+ ///
+ /// ## Examples
+ ///
+ /// > nand(False, False)
+ /// True
+ ///
+ /// > nand(False, True)
+ /// True
+ ///
+ /// > nand(True, False)
+ /// True
+ ///
+ /// > nand(True, True)
+ /// False
+ ///
+ pub fn nand(a: Bool, b: Bool) -> Bool {
+ case a, b {
+ False, False -> True
+ False, True -> True
+ True, False -> True
+ True, True -> False
+ }
}
-}
-/// Returns the exclusive or of two bools
-///
-/// ## Examples
-///
-/// > exclusive_or(False, False)
-/// False
-///
-/// > exclusive_or(False, True)
-/// True
-///
-/// > exclusive_or(True, False)
-/// True
-///
-/// > exclusive_or(True, True)
-/// False
-///
-pub fn exclusive_or(a: Bool, b: Bool) -> Bool {
- case a, b {
- False, False -> False
- False, True -> True
- True, False -> True
- True, True -> False
+ /// Returns the exclusive or of two bools
+ ///
+ /// ## Examples
+ ///
+ /// > exclusive_or(False, False)
+ /// False
+ ///
+ /// > exclusive_or(False, True)
+ /// True
+ ///
+ /// > exclusive_or(True, False)
+ /// True
+ ///
+ /// > exclusive_or(True, True)
+ /// False
+ ///
+ pub fn exclusive_or(a: Bool, b: Bool) -> Bool {
+ case a, b {
+ False, False -> False
+ False, True -> True
+ True, False -> True
+ True, True -> False
+ }
}
-}
-/// Returns the exclusive nor of two bools
-///
-/// ## Examples
-///
-/// > exclusive_nor(False, False)
-/// True
-///
-/// > exclusive_nor(False, True)
-/// False
-///
-/// > exclusive_nor(True, False)
-/// False
-///
-/// > exclusive_nor(True, True)
-/// True
-///
-pub fn exclusive_nor(a: Bool, b: Bool) -> Bool {
- case a, b {
- False, False -> True
- False, True -> False
- True, False -> False
- True, True -> True
+ /// Returns the exclusive nor of two bools
+ ///
+ /// ## Examples
+ ///
+ /// > exclusive_nor(False, False)
+ /// True
+ ///
+ /// > exclusive_nor(False, True)
+ /// False
+ ///
+ /// > exclusive_nor(True, False)
+ /// False
+ ///
+ /// > exclusive_nor(True, True)
+ /// True
+ ///
+ pub fn exclusive_nor(a: Bool, b: Bool) -> Bool {
+ case a, b {
+ False, False -> True
+ False, True -> False
+ True, False -> False
+ True, True -> True
+ }
}
-}
-/// Compares two bools and returns the first values Order to the second.
-///
-/// ## Examples
-///
-/// > import gleam/order
-/// > compare(True, False)
-/// order.Gt
-///
-pub fn compare(a: Bool, with b: Bool) -> Order {
- case a, b {
- True, True -> order.Eq
- True, False -> order.Gt
- False, False -> order.Eq
- False, True -> order.Lt
+ /// Compares two bools and returns the first values Order to the second.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/order
+ /// > compare(True, False)
+ /// order.Gt
+ ///
+ pub fn compare(a: Bool, with b: Bool) -> Order {
+ case a, b {
+ True, True -> order.Eq
+ True, False -> order.Gt
+ False, False -> order.Eq
+ False, True -> order.Lt
+ }
}
-}
-/// Returns True if either bool value is True.
-///
-/// ## Examples
-///
-/// > max(True, False)
-/// True
-///
-/// > max(False, True)
-/// True
-///
-/// > max(False, False)
-/// False
-///
-pub fn max(a: Bool, b: Bool) -> Bool {
- case a {
- True -> True
- False -> b
+ /// Returns True if either bool value is True.
+ ///
+ /// ## Examples
+ ///
+ /// > max(True, False)
+ /// True
+ ///
+ /// > max(False, True)
+ /// True
+ ///
+ /// > max(False, False)
+ /// False
+ ///
+ pub fn max(a: Bool, b: Bool) -> Bool {
+ case a {
+ True -> True
+ False -> b
+ }
}
-}
-/// Returns False if either bool value is False.
-///
-/// ## Examples
-///
-/// > max(True, False)
-/// False
-///
-/// > max(False, True)
-/// False
-///
-/// > max(False, False)
-/// False
-///
-pub fn min(a: Bool, b: Bool) -> Bool {
- case a {
- False -> False
- True -> b
+ /// Returns False if either bool value is False.
+ ///
+ /// ## Examples
+ ///
+ /// > max(True, False)
+ /// False
+ ///
+ /// > max(False, True)
+ /// False
+ ///
+ /// > max(False, False)
+ /// False
+ ///
+ pub fn min(a: Bool, b: Bool) -> Bool {
+ case a {
+ False -> False
+ True -> b
+ }
}
-}
-/// Returns a numeric representation of the given bool.
-///
-/// ## Examples
-///
-/// > to_int(True)
-/// 1
-///
-/// > to_int(False)
-/// 0
-///
-pub fn to_int(bool: Bool) -> Int {
- case bool {
- False -> 0
- True -> 1
+ /// Returns a numeric representation of the given bool.
+ ///
+ /// ## Examples
+ ///
+ /// > to_int(True)
+ /// 1
+ ///
+ /// > to_int(False)
+ /// 0
+ ///
+ pub fn to_int(bool: Bool) -> Int {
+ case bool {
+ False -> 0
+ True -> 1
+ }
}
}
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam
index 162045f..be2c9b7 100644
--- a/src/gleam/dynamic.gleam
+++ b/src/gleam/dynamic.gleam
@@ -1,641 +1,646 @@
-import gleam/atom
-import gleam/bit_string.{BitString}
-import gleam/list
-import gleam/map.{Map}
-import gleam/option.{None, Option, Some}
-import gleam/result
-import gleam/string_builder
-
-/// `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
-
-pub type Decoder(t) =
- fn(Dynamic) -> Result(t, String)
-
-/// Converts any Gleam data into `Dynamic` data.
-///
-pub external fn from(a) -> Dynamic =
- "gleam_stdlib" "identity"
-
-/// Unsafely casts a Dynamic value into any other type.
-///
-/// This is an escape hatch for the type system that may be useful when wrapping
-/// native Erlang APIs. It is to be used as a last measure only!
-///
-/// If you can avoid using this function, do!
-///
-pub external fn unsafe_coerce(Dynamic) -> a =
- "gleam_stdlib" "identity"
-
-/// Checks to see whether a Dynamic value is a bit_string, and return the bit_string if
-/// it is.
-///
-/// ## Examples
-///
-/// > bit_string(from("Hello")) == bit_string.from_string("Hello")
-/// True
-///
-/// > bit_string(from(123))
-/// Error("Expected a BitString, got `123`")
-///
-pub external fn bit_string(from: Dynamic) -> Result(BitString, String) =
- "gleam_stdlib" "decode_bit_string"
-
-/// Checks to see whether a Dynamic value is a string, and return the string if
-/// it is.
-///
-/// ## Examples
-///
-/// > string(from("Hello"))
-/// Ok("Hello")
-///
-/// > string(from(123))
-/// Error("Expected a String, got `123`")
-///
-pub fn string(from: Dynamic) -> Result(String, String) {
- bit_string(from)
- |> result.then(fn(raw) {
- case bit_string.to_string(raw) {
- Ok(string) -> Ok(string)
- Error(Nil) -> Error("Expected a string, got a bit_string")
- }
- })
-}
+if erlang {
+ import gleam/atom
+ import gleam/bit_string.{BitString}
+ import gleam/list
+ import gleam/map.{Map}
+ import gleam/option.{None, Option, Some}
+ import gleam/result
+ import gleam/string_builder
+
+ /// `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
+
+ pub type Decoder(t) =
+ fn(Dynamic) -> Result(t, String)
+
+ /// Converts any Gleam data into `Dynamic` data.
+ ///
+ pub external fn from(a) -> Dynamic =
+ "gleam_stdlib" "identity"
+
+ /// Unsafely casts a Dynamic value into any other type.
+ ///
+ /// This is an escape hatch for the type system that may be useful when wrapping
+ /// native Erlang APIs. It is to be used as a last measure only!
+ ///
+ /// If you can avoid using this function, do!
+ ///
+ pub external fn unsafe_coerce(Dynamic) -> a =
+ "gleam_stdlib" "identity"
+
+ /// Checks to see whether a Dynamic value is a bit_string, and return the bit_string if
+ /// it is.
+ ///
+ /// ## Examples
+ ///
+ /// > bit_string(from("Hello")) == bit_string.from_string("Hello")
+ /// True
+ ///
+ /// > bit_string(from(123))
+ /// Error("Expected a BitString, got `123`")
+ ///
+ pub external fn bit_string(from: Dynamic) -> Result(BitString, String) =
+ "gleam_stdlib" "decode_bit_string"
+
+ /// Checks to see whether a Dynamic value is a string, and return the string if
+ /// it is.
+ ///
+ /// ## Examples
+ ///
+ /// > string(from("Hello"))
+ /// Ok("Hello")
+ ///
+ /// > string(from(123))
+ /// Error("Expected a String, got `123`")
+ ///
+ pub fn string(from: Dynamic) -> Result(String, String) {
+ bit_string(from)
+ |> result.then(fn(raw) {
+ case bit_string.to_string(raw) {
+ Ok(string) -> Ok(string)
+ Error(Nil) -> Error("Expected a string, got a bit_string")
+ }
+ })
+ }
-/// Checks to see whether a Dynamic value is an int, and return the int if it
-/// is.
-///
-/// ## Examples
-///
-/// > 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"
-
-/// Checks to see whether a Dynamic value is an float, and return the float if
-/// it is.
-///
-/// ## Examples
-///
-/// > 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"
-
-/// Checks to see whether a Dynamic value is an atom, and return the atom if
-/// it is.
-///
-/// ## Examples
-///
-/// > import gleam/atom
-/// > atom(from(atom.create_from_string("hello")))
-/// OK("hello")
-///
-/// > atom(from(123))
-/// Error("Expected an Atom, got `123`")
-///
-pub external fn atom(from: Dynamic) -> Result(atom.Atom, String) =
- "gleam_stdlib" "decode_atom"
-
-/// Checks to see whether a Dynamic value is an bool, and return the bool if
-/// it is.
-///
-/// ## Examples
-///
-/// > 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"
-
-/// Checks to see whether a Dynamic value is a function that takes no arguments,
-/// and return the function if it is.
-///
-/// ## Examples
-///
-/// > import gleam/result
-/// > let f = fn() { 1 }
-/// > thunk(from(f)) |> result.is_ok
-/// 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"
-
-/// Checks to see whether a Dynamic value is a list, and return the list if it
-/// is.
-///
-/// If you wish to decode all the elements in the list use the `typed_list`
-/// instead.
-///
-/// ## Examples
-///
-/// > list(from(["a", "b", "c"]))
-/// Ok([from("a"), from("b"), from("c")])
-///
-/// > list(1)
-/// Error("Expected an Int, got a binary")
-///
-pub external fn list(from: Dynamic) -> Result(List(Dynamic), String) =
- "gleam_stdlib" "decode_list"
-
-/// Checks to see whether a Dynamic value is a result, and return the result if
-/// it is
-///
-/// ## Examples
-///
-/// > result(from(Ok(1)))
-/// Ok(Ok(from(1)))
-///
-/// > result(from(Error("boom")))
-/// Ok(Error(from("boom")))
-///
-/// > result(from(123))
-/// Error("Expected a 2 element tuple, got an int")
-///
-pub fn result(from: Dynamic) -> Result(Result(Dynamic, Dynamic), String) {
- try #(key, val) = tuple2(from)
-
- try tag = atom(key)
- let ok_atom = atom.create_from_string("ok")
- let error_atom = atom.create_from_string("error")
- case tag {
- tag if tag == ok_atom -> Ok(Ok(val))
- tag if tag == error_atom -> Ok(Error(val))
- tag ->
- "Expected a tag of \"ok\" or \"error\", got \""
- |> string_builder.from_string
- |> string_builder.append(atom.to_string(tag))
- |> string_builder.append("\"")
- |> string_builder.to_string
- |> Error
+ /// Checks to see whether a Dynamic value is an int, and return the int if it
+ /// is.
+ ///
+ /// ## Examples
+ ///
+ /// > 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"
+
+ /// Checks to see whether a Dynamic value is an float, and return the float if
+ /// it is.
+ ///
+ /// ## Examples
+ ///
+ /// > 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"
+
+ /// Checks to see whether a Dynamic value is an atom, and return the atom if
+ /// it is.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/atom
+ /// > atom(from(atom.create_from_string("hello")))
+ /// OK("hello")
+ ///
+ /// > atom(from(123))
+ /// Error("Expected an Atom, got `123`")
+ ///
+ pub external fn atom(from: Dynamic) -> Result(atom.Atom, String) =
+ "gleam_stdlib" "decode_atom"
+
+ /// Checks to see whether a Dynamic value is an bool, and return the bool if
+ /// it is.
+ ///
+ /// ## Examples
+ ///
+ /// > 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"
+
+ /// Checks to see whether a Dynamic value is a function that takes no arguments,
+ /// and return the function if it is.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/result
+ /// > let f = fn() { 1 }
+ /// > thunk(from(f)) |> result.is_ok
+ /// 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"
+
+ /// Checks to see whether a Dynamic value is a list, and return the list if it
+ /// is.
+ ///
+ /// If you wish to decode all the elements in the list use the `typed_list`
+ /// instead.
+ ///
+ /// ## Examples
+ ///
+ /// > list(from(["a", "b", "c"]))
+ /// Ok([from("a"), from("b"), from("c")])
+ ///
+ /// > list(1)
+ /// Error("Expected an Int, got a binary")
+ ///
+ pub external fn list(from: Dynamic) -> Result(List(Dynamic), String) =
+ "gleam_stdlib" "decode_list"
+
+ /// Checks to see whether a Dynamic value is a result, and return the result if
+ /// it is
+ ///
+ /// ## Examples
+ ///
+ /// > result(from(Ok(1)))
+ /// Ok(Ok(from(1)))
+ ///
+ /// > result(from(Error("boom")))
+ /// Ok(Error(from("boom")))
+ ///
+ /// > result(from(123))
+ /// Error("Expected a 2 element tuple, got an int")
+ ///
+ pub fn result(from: Dynamic) -> Result(Result(Dynamic, Dynamic), String) {
+ try #(key, val) = tuple2(from)
+
+ try tag = atom(key)
+ let ok_atom = atom.create_from_string("ok")
+ let error_atom = atom.create_from_string("error")
+ case tag {
+ tag if tag == ok_atom -> Ok(Ok(val))
+ tag if tag == error_atom -> Ok(Error(val))
+ tag ->
+ "Expected a tag of \"ok\" or \"error\", got \""
+ |> string_builder.from_string
+ |> string_builder.append(atom.to_string(tag))
+ |> string_builder.append("\"")
+ |> string_builder.to_string
+ |> Error
+ }
}
-}
-/// Checks to see whether a Dynamic value is a result of a particular type, and
-/// return the result if it is
-///
-/// The `ok` and `error` arguments are decoders for decoding the `Ok` and
-/// `Error` values of the result.
-///
-/// ## Examples
-///
-/// > typed_result(of: from(Ok(1)), ok: int, error: string)
-/// Ok(Ok(1))
-///
-/// > typed_result(of: from(Error("boom")), ok: int, error: string)
-/// Ok(Error("boom"))
-///
-/// > typed_result(of: from(123), ok: int, error: string)
-/// Error("Expected a 2 element tuple, got an int")
-///
-pub fn typed_result(
- of dynamic: Dynamic,
- ok decode_ok: Decoder(a),
- error decode_error: Decoder(e),
-) -> Result(Result(a, e), String) {
- try inner_result = result(dynamic)
-
- case inner_result {
- Ok(raw) ->
- raw
- |> decode_ok
- |> result.map(Ok)
- Error(raw) ->
- raw
- |> decode_error
- |> result.map(Error)
+ /// Checks to see whether a Dynamic value is a result of a particular type, and
+ /// return the result if it is
+ ///
+ /// The `ok` and `error` arguments are decoders for decoding the `Ok` and
+ /// `Error` values of the result.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_result(of: from(Ok(1)), ok: int, error: string)
+ /// Ok(Ok(1))
+ ///
+ /// > typed_result(of: from(Error("boom")), ok: int, error: string)
+ /// Ok(Error("boom"))
+ ///
+ /// > typed_result(of: from(123), ok: int, error: string)
+ /// Error("Expected a 2 element tuple, got an int")
+ ///
+ pub fn typed_result(
+ of dynamic: Dynamic,
+ ok decode_ok: Decoder(a),
+ error decode_error: Decoder(e),
+ ) -> Result(Result(a, e), String) {
+ try inner_result = result(dynamic)
+
+ case inner_result {
+ Ok(raw) ->
+ raw
+ |> decode_ok
+ |> result.map(Ok)
+ Error(raw) ->
+ raw
+ |> decode_error
+ |> result.map(Error)
+ }
}
-}
-/// Checks to see whether a Dynamic value is a list of a particular type, and
-/// return the list if it is.
-///
-/// The second argument is a decoder function used to decode the elements of
-/// the list. The list is only decoded if all elements in the list can be
-/// successfully decoded using this function.
-///
-/// If you do not wish to decode all the elements in the list use the `list`
-/// function instead.
-///
-/// ## Examples
-///
-/// > typed_list(from(["a", "b", "c"]), of: string)
-/// Ok(["a", "b", "c"])
-///
-/// > typed_list(from([1, 2, 3]), of: string)
-/// Error("Expected an Int, got a binary")
-///
-/// > typed_list(from("ok"), of: string)
-/// Error("Expected a List, got a binary")
-///
-pub fn typed_list(
- from dynamic: Dynamic,
- of decoder_type: fn(Dynamic) -> Result(inner, String),
-) -> Result(List(inner), String) {
- dynamic
- |> list
- |> result.then(list.try_map(_, decoder_type))
-}
+ /// Checks to see whether a Dynamic value is a list of a particular type, and
+ /// return the list if it is.
+ ///
+ /// The second argument is a decoder function used to decode the elements of
+ /// the list. The list is only decoded if all elements in the list can be
+ /// successfully decoded using this function.
+ ///
+ /// If you do not wish to decode all the elements in the list use the `list`
+ /// function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_list(from(["a", "b", "c"]), of: string)
+ /// Ok(["a", "b", "c"])
+ ///
+ /// > typed_list(from([1, 2, 3]), of: string)
+ /// Error("Expected an Int, got a binary")
+ ///
+ /// > typed_list(from("ok"), of: string)
+ /// Error("Expected a List, got a binary")
+ ///
+ pub fn typed_list(
+ from dynamic: Dynamic,
+ of decoder_type: fn(Dynamic) -> Result(inner, String),
+ ) -> Result(List(inner), String) {
+ dynamic
+ |> list
+ |> result.then(list.try_map(_, decoder_type))
+ }
-/// Checks to see if a Dynamic value is an Option of a particular type, and return
-/// the Option if it is.
-///
-/// The second argument is a decoder function used to decode the elements of
-/// the list. The list is only decoded if all elements in the list can be
-/// successfully decoded using this function.
-///
-/// ## Examples
-///
-/// > option(from("Hello"), string)
-/// Ok(Some("Hello"))
-///
-/// > option(from(atom.from_string("null")), string)
-/// Ok(None)
-///
-/// > option(from(123), string)
-/// Error("Expected a bit_string, got an int")
-///
-pub fn option(
- from dynamic: Dynamic,
- of decoder: Decoder(inner),
-) -> Result(Option(inner), String) {
- let Ok(null) = atom.from_string("null")
- case atom(dynamic), decoder(dynamic) {
- Ok(atom), _ if atom == null -> Ok(None)
- _, Ok(result) -> Ok(Some(result))
- _, Error(msg) -> Error(msg)
+ /// Checks to see if a Dynamic value is an Option of a particular type, and return
+ /// the Option if it is.
+ ///
+ /// The second argument is a decoder function used to decode the elements of
+ /// the list. The list is only decoded if all elements in the list can be
+ /// successfully decoded using this function.
+ ///
+ /// ## Examples
+ ///
+ /// > option(from("Hello"), string)
+ /// Ok(Some("Hello"))
+ ///
+ /// > option(from(atom.from_string("null")), string)
+ /// Ok(None)
+ ///
+ /// > option(from(123), string)
+ /// Error("Expected a bit_string, got an int")
+ ///
+ pub fn option(
+ from dynamic: Dynamic,
+ of decoder: Decoder(inner),
+ ) -> Result(Option(inner), String) {
+ let Ok(null) = atom.from_string("null")
+ case atom(dynamic), decoder(dynamic) {
+ Ok(atom), _ if atom == null -> Ok(None)
+ _, Ok(result) -> Ok(Some(result))
+ _, Error(msg) -> Error(msg)
+ }
}
-}
-/// Checks to see if a Dynamic value is a map with a specific field, and return
-/// the value of the field if it is.
-///
-/// This will not succeed on a record.
-///
-/// ## Examples
-///
-/// > import gleam/map
-/// > field(from(map.new("Hello", "World")), "Hello")
-/// Ok(Dynamic)
-///
-/// > field(from(123), "Hello")
-/// Error("Expected a map with key `\"Hello\"`, got an Int")
-///
-pub external fn field(from: Dynamic, named: a) -> Result(Dynamic, String) =
- "gleam_stdlib" "decode_field"
-
-/// Checks to see if the Dynamic value is a tuple large enough to have a certain
-/// index, and return the value of that index if it is.
-///
-/// ## Examples
-///
-/// > element(from(#(1, 2)), 0)
-/// Ok(from(1))
-///
-/// > element(from(#(1, 2)), 2)
-/// Error("Expected a tuple of at least 3 size, got a tuple of 2 size")
-///
-/// > element(from(""), 2)
-/// Error("Expected a tuple, got a binary")
-///
-pub external fn element(from: Dynamic, position: Int) -> Result(Dynamic, String) =
- "gleam_stdlib" "decode_element"
-
-/// Checks to see if the Dynamic value is a 2 element tuple.
-///
-/// If you do not wish to decode all the elements in the tuple use the
-/// `typed_tuple2` function instead.
-///
-/// ## Examples
-///
-/// > tuple2(from(#(1, 2)))
-/// Ok(#(from(1), from(2)))
-///
-/// > tuple2(from(#(1, 2, 3)))
-/// Error("Expected a 2 element tuple")
-///
-/// > tuple2(from(""))
-/// Error("Expected a tuple, got a binary")
-///
-pub external fn tuple2(from: Dynamic) -> Result(#(Dynamic, Dynamic), String) =
- "gleam_stdlib" "decode_tuple2"
-
-/// Checks to see if the Dynamic value is a 2 element tuple containing two
-/// specifically typed elements.
-///
-/// If you wish to decode all the elements in the list use the `typed_tuple2`
-/// instead.
-///
-/// ## Examples
-///
-/// > typed_tuple2(from(#(1, 2)), int, int)
-/// Ok(#(1, 2))
-///
-/// > typed_tuple2(from(#(1, 2.0)), int, float)
-/// Ok(#(1, 2.0))
-///
-/// > typed_tuple2(from(#(1, 2, 3)), int, float)
-/// Error("Expected a 2 element tuple, got a 3 element tuple")
-///
-/// > typed_tuple2(from(""), int, float)
-/// Error("Expected a tuple, got a binary")
-///
-pub fn typed_tuple2(
- from tup: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
-) -> Result(#(a, b), String) {
- try #(first, second) = tuple2(tup)
- try a = decode_first(first)
- try b = decode_second(second)
- Ok(#(a, b))
-}
+ /// Checks to see if a Dynamic value is a map with a specific field, and return
+ /// the value of the field if it is.
+ ///
+ /// This will not succeed on a record.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/map
+ /// > field(from(map.new("Hello", "World")), "Hello")
+ /// Ok(Dynamic)
+ ///
+ /// > field(from(123), "Hello")
+ /// Error("Expected a map with key `\"Hello\"`, got an Int")
+ ///
+ pub external fn field(from: Dynamic, named: a) -> Result(Dynamic, String) =
+ "gleam_stdlib" "decode_field"
+
+ /// Checks to see if the Dynamic value is a tuple large enough to have a certain
+ /// index, and return the value of that index if it is.
+ ///
+ /// ## Examples
+ ///
+ /// > element(from(#(1, 2)), 0)
+ /// Ok(from(1))
+ ///
+ /// > element(from(#(1, 2)), 2)
+ /// Error("Expected a tuple of at least 3 size, got a tuple of 2 size")
+ ///
+ /// > element(from(""), 2)
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub external fn element(
+ from: Dynamic,
+ position: Int,
+ ) -> Result(Dynamic, String) =
+ "gleam_stdlib" "decode_element"
+
+ /// Checks to see if the Dynamic value is a 2 element tuple.
+ ///
+ /// If you do not wish to decode all the elements in the tuple use the
+ /// `typed_tuple2` function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > tuple2(from(#(1, 2)))
+ /// Ok(#(from(1), from(2)))
+ ///
+ /// > tuple2(from(#(1, 2, 3)))
+ /// Error("Expected a 2 element tuple")
+ ///
+ /// > tuple2(from(""))
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub external fn tuple2(from: Dynamic) -> Result(#(Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_tuple2"
+
+ /// Checks to see if the Dynamic value is a 2 element tuple containing two
+ /// specifically typed elements.
+ ///
+ /// If you wish to decode all the elements in the list use the `typed_tuple2`
+ /// instead.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_tuple2(from(#(1, 2)), int, int)
+ /// Ok(#(1, 2))
+ ///
+ /// > typed_tuple2(from(#(1, 2.0)), int, float)
+ /// Ok(#(1, 2.0))
+ ///
+ /// > typed_tuple2(from(#(1, 2, 3)), int, float)
+ /// Error("Expected a 2 element tuple, got a 3 element tuple")
+ ///
+ /// > typed_tuple2(from(""), int, float)
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub fn typed_tuple2(
+ from tup: Dynamic,
+ first decode_first: Decoder(a),
+ second decode_second: Decoder(b),
+ ) -> Result(#(a, b), String) {
+ try #(first, second) = tuple2(tup)
+ try a = decode_first(first)
+ try b = decode_second(second)
+ Ok(#(a, b))
+ }
-/// Checks to see if the Dynamic value is a 3 element tuple.
-///
-/// If you do not wish to decode all the elements in the tuple use the
-/// `typed_tuple3` function instead.
-///
-/// ## Examples
-///
-/// > tuple3(from(#(1, 2, 3)))
-/// Ok(#(from(1), from(2), from(3)))
-///
-/// > tuple3(from(#(1, 2)))
-/// Error("Expected a 3 element tuple")
-///
-/// > tuple3(from(""))
-/// Error("Expected a tuple, got a binary")
-///
-pub external fn tuple3(
- from: Dynamic,
-) -> Result(#(Dynamic, Dynamic, Dynamic), String) =
- "gleam_stdlib" "decode_tuple3"
-
-/// Checks to see if the Dynamic value is a 3 element tuple containing two
-/// specifically typed elements.
-///
-/// If you wish to decode all the elements in the list use the `typed_tuple3`
-/// instead.
-///
-/// ## Examples
-///
-/// > typed_tuple3(from(#(1, 2, 3)), int, int, int)
-/// Ok(#(1, 2, 3))
-///
-/// > typed_tuple3(from(#(1, 2.0, "3")), int, float, string)
-/// Ok(#(1, 2.0, "3"))
-///
-/// > typed_tuple3(from(#(1, 2)), int, float, string)
-/// Error("Expected a 3 element tuple, got a 2 element tuple")
-///
-/// > typed_tuple3(from(""), int, float, string)
-/// Error("Expected a tuple, got a binary")
-///
-pub fn typed_tuple3(
- from tup: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
-) -> Result(#(a, b, c), String) {
- try #(first, second, third) = tuple3(tup)
- try a = decode_first(first)
- try b = decode_second(second)
- try c = decode_third(third)
- Ok(#(a, b, c))
-}
+ /// Checks to see if the Dynamic value is a 3 element tuple.
+ ///
+ /// If you do not wish to decode all the elements in the tuple use the
+ /// `typed_tuple3` function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > tuple3(from(#(1, 2, 3)))
+ /// Ok(#(from(1), from(2), from(3)))
+ ///
+ /// > tuple3(from(#(1, 2)))
+ /// Error("Expected a 3 element tuple")
+ ///
+ /// > tuple3(from(""))
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub external fn tuple3(
+ from: Dynamic,
+ ) -> Result(#(Dynamic, Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_tuple3"
+
+ /// Checks to see if the Dynamic value is a 3 element tuple containing two
+ /// specifically typed elements.
+ ///
+ /// If you wish to decode all the elements in the list use the `typed_tuple3`
+ /// instead.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_tuple3(from(#(1, 2, 3)), int, int, int)
+ /// Ok(#(1, 2, 3))
+ ///
+ /// > typed_tuple3(from(#(1, 2.0, "3")), int, float, string)
+ /// Ok(#(1, 2.0, "3"))
+ ///
+ /// > typed_tuple3(from(#(1, 2)), int, float, string)
+ /// Error("Expected a 3 element tuple, got a 2 element tuple")
+ ///
+ /// > typed_tuple3(from(""), int, float, string)
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub fn typed_tuple3(
+ from tup: Dynamic,
+ first decode_first: Decoder(a),
+ second decode_second: Decoder(b),
+ third decode_third: Decoder(c),
+ ) -> Result(#(a, b, c), String) {
+ try #(first, second, third) = tuple3(tup)
+ try a = decode_first(first)
+ try b = decode_second(second)
+ try c = decode_third(third)
+ Ok(#(a, b, c))
+ }
-/// Checks to see if the Dynamic value is a 4 element tuple.
-///
-/// If you do not wish to decode all the elements in the tuple use the
-/// `typed_tuple4` function instead.
-///
-/// ## Examples
-///
-/// > tuple4(from(#(1, 2, 3, 4)))
-/// Ok(#(from(1), from(2), from(3), from(4)))
-///
-/// > tuple4(from(#(1, 2)))
-/// Error("Expected a 4 element tuple")
-///
-/// > tuple4(from(""))
-/// Error("Expected a tuple, got a binary")
-///
-pub external fn tuple4(
- from: Dynamic,
-) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), String) =
- "gleam_stdlib" "decode_tuple4"
-
-/// Checks to see if the Dynamic value is a 4 element tuple containing two
-/// specifically typed elements.
-///
-/// If you wish to decode all the elements in the list use the `typed_tuple4`
-/// instead.
-///
-/// ## Examples
-///
-/// > typed_tuple4(from(#(1, 2, 3, 4)), int, int, int, int)
-/// Ok(#(1, 2, 3, 4))
-///
-/// > typed_tuple4(from(#(1, 2.0, "3", 4)), int, float, string, int)
-/// Ok(#(1, 2.0, "3", 4))
-///
-/// > typed_tuple4(from(#(1, 2)), int, float, string, int)
-/// Error("Expected a 4 element tuple, got a 2 element tuple")
-///
-/// > typed_tuple4(from(""), int, float, string, int)
-/// Error("Expected a tuple, got a binary")
-///
-pub fn typed_tuple4(
- from tup: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
- fourth decode_fourth: Decoder(d),
-) -> Result(#(a, b, c, d), String) {
- try #(first, second, third, fourth) = tuple4(tup)
- try a = decode_first(first)
- try b = decode_second(second)
- try c = decode_third(third)
- try d = decode_fourth(fourth)
- Ok(#(a, b, c, d))
-}
+ /// Checks to see if the Dynamic value is a 4 element tuple.
+ ///
+ /// If you do not wish to decode all the elements in the tuple use the
+ /// `typed_tuple4` function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > tuple4(from(#(1, 2, 3, 4)))
+ /// Ok(#(from(1), from(2), from(3), from(4)))
+ ///
+ /// > tuple4(from(#(1, 2)))
+ /// Error("Expected a 4 element tuple")
+ ///
+ /// > tuple4(from(""))
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub external fn tuple4(
+ from: Dynamic,
+ ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_tuple4"
+
+ /// Checks to see if the Dynamic value is a 4 element tuple containing two
+ /// specifically typed elements.
+ ///
+ /// If you wish to decode all the elements in the list use the `typed_tuple4`
+ /// instead.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_tuple4(from(#(1, 2, 3, 4)), int, int, int, int)
+ /// Ok(#(1, 2, 3, 4))
+ ///
+ /// > typed_tuple4(from(#(1, 2.0, "3", 4)), int, float, string, int)
+ /// Ok(#(1, 2.0, "3", 4))
+ ///
+ /// > typed_tuple4(from(#(1, 2)), int, float, string, int)
+ /// Error("Expected a 4 element tuple, got a 2 element tuple")
+ ///
+ /// > typed_tuple4(from(""), int, float, string, int)
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub fn typed_tuple4(
+ from tup: Dynamic,
+ first decode_first: Decoder(a),
+ second decode_second: Decoder(b),
+ third decode_third: Decoder(c),
+ fourth decode_fourth: Decoder(d),
+ ) -> Result(#(a, b, c, d), String) {
+ try #(first, second, third, fourth) = tuple4(tup)
+ try a = decode_first(first)
+ try b = decode_second(second)
+ try c = decode_third(third)
+ try d = decode_fourth(fourth)
+ Ok(#(a, b, c, d))
+ }
-/// Checks to see if the Dynamic value is a 5 element tuple.
-///
-/// If you do not wish to decode all the elements in the tuple use the
-/// `typed_tuple5` function instead.
-///
-/// ## Examples
-///
-/// > tuple5(from(#(1, 2, 3, 4, 5)))
-/// Ok(#(from(1), from(2), from(3), from(4), from(5)))
-///
-/// > tuple5(from(#(1, 2)))
-/// Error("Expected a 5 element tuple")
-///
-/// > tuple5(from(""))
-/// Error("Expected a tuple, got a binary")
-///
-pub external fn tuple5(
- from: Dynamic,
-) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), String) =
- "gleam_stdlib" "decode_tuple5"
-
-/// Checks to see if the Dynamic value is a 5 element tuple containing two
-/// specifically typed elements.
-///
-/// If you wish to decode all the elements in the list use the `typed_tuple5`
-/// instead.
-///
-/// ## Examples
-///
-/// > typed_tuple5(from(#(1, 2, 3, 4, 5)), int, int, int, int, int)
-/// Ok(#(1, 2, 3, 4, 5))
-///
-/// > typed_tuple5(from(#(1, 2.0, "3", 4, 5)), int, float, string, int, int)
-/// Ok(#(1, 2.0, "3", 4, 5))
-///
-/// > typed_tuple5(from(#(1, 2)), int, float, string, int, int)
-/// Error("Expected a 5 element tuple, got a 2 element tuple")
-///
-/// > typed_tuple5(from(""), int, float, string, int, int)
-/// Error("Expected a tuple, got a binary")
-///
-pub fn typed_tuple5(
- from tup: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
- fourth decode_fourth: Decoder(d),
- fifth decode_fifth: Decoder(e),
-) -> Result(#(a, b, c, d, e), String) {
- try #(first, second, third, fourth, fifth) = tuple5(tup)
- try a = decode_first(first)
- try b = decode_second(second)
- try c = decode_third(third)
- try d = decode_fourth(fourth)
- try e = decode_fifth(fifth)
- Ok(#(a, b, c, d, e))
-}
+ /// Checks to see if the Dynamic value is a 5 element tuple.
+ ///
+ /// If you do not wish to decode all the elements in the tuple use the
+ /// `typed_tuple5` function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > tuple5(from(#(1, 2, 3, 4, 5)))
+ /// Ok(#(from(1), from(2), from(3), from(4), from(5)))
+ ///
+ /// > tuple5(from(#(1, 2)))
+ /// Error("Expected a 5 element tuple")
+ ///
+ /// > tuple5(from(""))
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub external fn tuple5(
+ from: Dynamic,
+ ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_tuple5"
+
+ /// Checks to see if the Dynamic value is a 5 element tuple containing two
+ /// specifically typed elements.
+ ///
+ /// If you wish to decode all the elements in the list use the `typed_tuple5`
+ /// instead.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_tuple5(from(#(1, 2, 3, 4, 5)), int, int, int, int, int)
+ /// Ok(#(1, 2, 3, 4, 5))
+ ///
+ /// > typed_tuple5(from(#(1, 2.0, "3", 4, 5)), int, float, string, int, int)
+ /// Ok(#(1, 2.0, "3", 4, 5))
+ ///
+ /// > typed_tuple5(from(#(1, 2)), int, float, string, int, int)
+ /// Error("Expected a 5 element tuple, got a 2 element tuple")
+ ///
+ /// > typed_tuple5(from(""), int, float, string, int, int)
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub fn typed_tuple5(
+ from tup: Dynamic,
+ first decode_first: Decoder(a),
+ second decode_second: Decoder(b),
+ third decode_third: Decoder(c),
+ fourth decode_fourth: Decoder(d),
+ fifth decode_fifth: Decoder(e),
+ ) -> Result(#(a, b, c, d, e), String) {
+ try #(first, second, third, fourth, fifth) = tuple5(tup)
+ try a = decode_first(first)
+ try b = decode_second(second)
+ try c = decode_third(third)
+ try d = decode_fourth(fourth)
+ try e = decode_fifth(fifth)
+ Ok(#(a, b, c, d, e))
+ }
-/// Checks to see if the Dynamic value is a 6 element tuple.
-///
-/// If you do not wish to decode all the elements in the tuple use the
-/// `typed_tuple6` function instead.
-///
-/// ## Examples
-///
-/// > tuple6(from(#(1, 2, 3, 4, 5, 6)))
-/// Ok(#(from(1), from(2), from(3), from(4), from(5), from(6)))
-///
-/// > tuple6(from(#(1, 2)))
-/// Error("Expected a 6 element tuple")
-///
-/// > tuple6(from(""))
-/// Error("Expected a tuple, got a binary")
-///
-pub external fn tuple6(
- from: Dynamic,
-) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), String) =
- "gleam_stdlib" "decode_tuple6"
-
-/// Checks to see if the Dynamic value is a 6 element tuple containing two
-/// specifically typed elements.
-///
-/// If you wish to decode all the elements in the list use the `typed_tuple6`
-/// instead.
-///
-/// ## Examples
-///
-/// > typed_tuple6(from(#(1, 2, 3, 4, 5, 6)), int, int, int, int, int, int)
-/// Ok(#(1, 2, 3, 4, 5, 6))
-///
-/// > typed_tuple6(from(#(1, 2.0, "3", 4, 5, 6)), int, float, string, int, int)
-/// Ok(#(1, 2.0, "3", 4, 5, 6))
-///
-/// > typed_tuple6(from(#(1, 2)), int, float, string, int, int, int)
-/// Error("Expected a 6 element tuple, got a 2 element tuple")
-///
-/// > typed_tuple6(from(""), int, float, string, int, int, int)
-/// Error("Expected a tuple, got a binary")
-///
-pub fn typed_tuple6(
- from tup: Dynamic,
- first decode_first: Decoder(a),
- second decode_second: Decoder(b),
- third decode_third: Decoder(c),
- fourth decode_fourth: Decoder(d),
- fifth decode_fifth: Decoder(e),
- sixth decode_sixth: Decoder(f),
-) -> Result(#(a, b, c, d, e, f), String) {
- try #(first, second, third, fourth, fifth, sixth) = tuple6(tup)
- try a = decode_first(first)
- try b = decode_second(second)
- try c = decode_third(third)
- try d = decode_fourth(fourth)
- try e = decode_fifth(fifth)
- try f = decode_sixth(sixth)
- Ok(#(a, b, c, d, e, f))
-}
+ /// Checks to see if the Dynamic value is a 6 element tuple.
+ ///
+ /// If you do not wish to decode all the elements in the tuple use the
+ /// `typed_tuple6` function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > tuple6(from(#(1, 2, 3, 4, 5, 6)))
+ /// Ok(#(from(1), from(2), from(3), from(4), from(5), from(6)))
+ ///
+ /// > tuple6(from(#(1, 2)))
+ /// Error("Expected a 6 element tuple")
+ ///
+ /// > tuple6(from(""))
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub external fn tuple6(
+ from: Dynamic,
+ ) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_tuple6"
+
+ /// Checks to see if the Dynamic value is a 6 element tuple containing two
+ /// specifically typed elements.
+ ///
+ /// If you wish to decode all the elements in the list use the `typed_tuple6`
+ /// instead.
+ ///
+ /// ## Examples
+ ///
+ /// > typed_tuple6(from(#(1, 2, 3, 4, 5, 6)), int, int, int, int, int, int)
+ /// Ok(#(1, 2, 3, 4, 5, 6))
+ ///
+ /// > typed_tuple6(from(#(1, 2.0, "3", 4, 5, 6)), int, float, string, int, int)
+ /// Ok(#(1, 2.0, "3", 4, 5, 6))
+ ///
+ /// > typed_tuple6(from(#(1, 2)), int, float, string, int, int, int)
+ /// Error("Expected a 6 element tuple, got a 2 element tuple")
+ ///
+ /// > typed_tuple6(from(""), int, float, string, int, int, int)
+ /// Error("Expected a tuple, got a binary")
+ ///
+ pub fn typed_tuple6(
+ from tup: Dynamic,
+ first decode_first: Decoder(a),
+ second decode_second: Decoder(b),
+ third decode_third: Decoder(c),
+ fourth decode_fourth: Decoder(d),
+ fifth decode_fifth: Decoder(e),
+ sixth decode_sixth: Decoder(f),
+ ) -> Result(#(a, b, c, d, e, f), String) {
+ try #(first, second, third, fourth, fifth, sixth) = tuple6(tup)
+ try a = decode_first(first)
+ try b = decode_second(second)
+ try c = decode_third(third)
+ try d = decode_fourth(fourth)
+ try e = decode_fifth(fifth)
+ try f = decode_sixth(sixth)
+ Ok(#(a, b, c, d, e, f))
+ }
-/// Checks to see if the Dynamic value is map.
-///
-/// ## Examples
-///
-/// > import gleam/map
-/// > map(from(map.new()))
-/// Ok(map.new())
-///
-/// > map(from(1))
-/// Error("Expected a 2 element tuple, got an int")
-///
-/// > map(from(""))
-/// Error("Expected a map, got a binary")
-///
-pub external fn map(from: Dynamic) -> Result(Map(Dynamic, Dynamic), String) =
- "gleam_stdlib" "decode_map"
-
-/// Joins multiple decoders into one. When run they will each be tried in turn
-/// until one succeeds, or they all fail.
-///
-/// ## Examples
-///
-/// > import gleam/result
-/// > let bool_or_string = any(_, of: [
-/// > string,
-/// > fn(x) { result.map(bool(x), fn(_) { "a bool" }) }
-/// > ])
-/// > bool_or_string(from("ok"))
-/// Ok("ok")
-///
-/// > bool_or_string(from(True))
-/// Ok("a bool")
-///
-/// > bool_or_string(from(1))
-/// Error("Unexpected value")
-///
-pub fn any(
- from data: Dynamic,
- of decoders: List(Decoder(t)),
-) -> Result(t, String) {
- decoders
- |> list.find_map(fn(decoder) { decoder(data) })
- |> result.map_error(fn(_) { "Unexpected value" })
+ /// Checks to see if the Dynamic value is map.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/map
+ /// > map(from(map.new()))
+ /// Ok(map.new())
+ ///
+ /// > map(from(1))
+ /// Error("Expected a 2 element tuple, got an int")
+ ///
+ /// > map(from(""))
+ /// Error("Expected a map, got a binary")
+ ///
+ pub external fn map(from: Dynamic) -> Result(Map(Dynamic, Dynamic), String) =
+ "gleam_stdlib" "decode_map"
+
+ /// Joins multiple decoders into one. When run they will each be tried in turn
+ /// until one succeeds, or they all fail.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/result
+ /// > let bool_or_string = any(_, of: [
+ /// > string,
+ /// > fn(x) { result.map(bool(x), fn(_) { "a bool" }) }
+ /// > ])
+ /// > bool_or_string(from("ok"))
+ /// Ok("ok")
+ ///
+ /// > bool_or_string(from(True))
+ /// Ok("a bool")
+ ///
+ /// > bool_or_string(from(1))
+ /// Error("Unexpected value")
+ ///
+ pub fn any(
+ from data: Dynamic,
+ of decoders: List(Decoder(t)),
+ ) -> Result(t, String) {
+ decoders
+ |> list.find_map(fn(decoder) { decoder(data) })
+ |> result.map_error(fn(_) { "Unexpected value" })
+ }
}
diff --git a/src/gleam/float.gleam b/src/gleam/float.gleam
index 2a646c2..ed1d3ab 100644
--- a/src/gleam/float.gleam
+++ b/src/gleam/float.gleam
@@ -1,228 +1,230 @@
-import gleam/string_builder
-import gleam/order.{Order}
-
-pub type Float =
- Float
-
-/// Attempts to parse a string as a float, returning `Error(Nil)` if it was not
-/// possible.
-///
-/// ## Examples
-/// > parse("2.3")
-/// Ok(2.3)
-///
-/// > parse("ABC")
-/// Error(Nil)
-///
-pub external fn parse(String) -> Result(Float, Nil) =
- "gleam_stdlib" "parse_float"
-
-/// Returns the string representation of the provided float.
-///
-/// ## Examples
-/// > to_string(2.3)
-/// "2.3"
-///
-pub fn to_string(f: Float) -> String {
- f
- |> string_builder.from_float
- |> string_builder.to_string
-}
+if erlang {
+ import gleam/string_builder
+ import gleam/order.{Order}
+
+ pub type Float =
+ Float
+
+ /// Attempts to parse a string as a float, returning `Error(Nil)` if it was not
+ /// possible.
+ ///
+ /// ## Examples
+ /// > parse("2.3")
+ /// Ok(2.3)
+ ///
+ /// > parse("ABC")
+ /// Error(Nil)
+ ///
+ pub external fn parse(String) -> Result(Float, Nil) =
+ "gleam_stdlib" "parse_float"
+
+ /// Returns the string representation of the provided float.
+ ///
+ /// ## Examples
+ /// > to_string(2.3)
+ /// "2.3"
+ ///
+ pub fn to_string(f: Float) -> String {
+ f
+ |> string_builder.from_float
+ |> string_builder.to_string
+ }
-/// Restricts a Float between a lower and upper bound
-///
-/// ## Examples
-///
-/// ```
-/// > clamp(1.2, min: 1.4, max: 1.6)
-/// 1.4
-/// ```
-///
-pub fn clamp(n: Float, min min_bound: Float, max max_bound: Float) -> Float {
- n
- |> min(max_bound)
- |> max(min_bound)
-}
+ /// Restricts a Float between a lower and upper bound
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > clamp(1.2, min: 1.4, max: 1.6)
+ /// 1.4
+ /// ```
+ ///
+ pub fn clamp(n: Float, min min_bound: Float, max max_bound: Float) -> Float {
+ n
+ |> min(max_bound)
+ |> max(min_bound)
+ }
-/// Compares two floats, returning an order.
-///
-/// ## Examples
-/// > compare(2.0, 2.3)
-/// Lt
-///
-pub fn compare(a: Float, with b: Float) -> Order {
- case a == b {
- True -> order.Eq
- False ->
- case a <. b {
- True -> order.Lt
- False -> order.Gt
- }
+ /// Compares two floats, returning an order.
+ ///
+ /// ## Examples
+ /// > compare(2.0, 2.3)
+ /// Lt
+ ///
+ pub fn compare(a: Float, with b: Float) -> Order {
+ case a == b {
+ True -> order.Eq
+ False ->
+ case a <. b {
+ True -> order.Lt
+ False -> order.Gt
+ }
+ }
}
-}
-/// Compares two floats, returning the smaller of the two.
-///
-/// ## Examples
-///
-/// > min(2.0, 2.3)
-/// 2.0
-///
-pub fn min(a: Float, b: Float) -> Float {
- case a <. b {
- True -> a
- False -> b
+ /// Compares two floats, returning the smaller of the two.
+ ///
+ /// ## Examples
+ ///
+ /// > min(2.0, 2.3)
+ /// 2.0
+ ///
+ pub fn min(a: Float, b: Float) -> Float {
+ case a <. b {
+ True -> a
+ False -> b
+ }
}
-}
-/// Compares two floats, returning the larger of the two.
-///
-/// ## Examples
-///
-/// > max(2.0, 2.3)
-/// 2.3
-///
-pub fn max(a: Float, b: Float) -> Float {
- case a >. b {
- True -> a
- False -> b
+ /// Compares two floats, returning the larger of the two.
+ ///
+ /// ## Examples
+ ///
+ /// > max(2.0, 2.3)
+ /// 2.3
+ ///
+ pub fn max(a: Float, b: Float) -> Float {
+ case a >. b {
+ True -> a
+ False -> b
+ }
}
-}
-/// Rounds the value to the next highest whole number as a float.
-///
-/// ## Examples
-///
-/// > 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
-///
-/// > 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
-///
-/// > 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
-///
-/// > truncate(2.4343434847383438)
-/// 2
-///
-pub external fn truncate(Float) -> Int =
- "erlang" "trunc"
-
-/// Returns the absolute value of the input as a float.
-///
-/// ## Examples
-///
-/// > absolute_value(-12.5)
-/// 12.5
-///
-/// > absolute_value(10.2)
-/// 10.2
-///
-pub external fn absolute_value(Float) -> Float =
- "erlang" "abs"
-
-/// Returns the results of the base being raised to the power of the
-/// exponent, as a float.
-///
-/// ## Examples
-///
-/// > power(2.0, 2.0)
-/// 4.0
-///
-/// > power(8.0, 1.5)
-/// 64.0
-///
-pub external fn power(base: Float, exponent: Float) -> Float =
- "math" "pow"
-
-/// Returns the square root of the input as a float.
-///
-/// ## Examples
-///
-/// > square_root(4.0)
-/// Ok(2.0)
-///
-/// > square_root(-16.0)
-/// Error(Nil)
-///
-pub fn square_root(number: Float) -> Result(Float, Nil) {
- case number <. 0.0 {
- True -> Error(Nil)
- False -> Ok(power(number, 0.5))
+ /// Rounds the value to the next highest whole number as a float.
+ ///
+ /// ## Examples
+ ///
+ /// > 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
+ ///
+ /// > 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
+ ///
+ /// > 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
+ ///
+ /// > truncate(2.4343434847383438)
+ /// 2
+ ///
+ pub external fn truncate(Float) -> Int =
+ "erlang" "trunc"
+
+ /// Returns the absolute value of the input as a float.
+ ///
+ /// ## Examples
+ ///
+ /// > absolute_value(-12.5)
+ /// 12.5
+ ///
+ /// > absolute_value(10.2)
+ /// 10.2
+ ///
+ pub external fn absolute_value(Float) -> Float =
+ "erlang" "abs"
+
+ /// Returns the results of the base being raised to the power of the
+ /// exponent, as a float.
+ ///
+ /// ## Examples
+ ///
+ /// > power(2.0, 2.0)
+ /// 4.0
+ ///
+ /// > power(8.0, 1.5)
+ /// 64.0
+ ///
+ pub external fn power(base: Float, exponent: Float) -> Float =
+ "math" "pow"
+
+ /// Returns the square root of the input as a float.
+ ///
+ /// ## Examples
+ ///
+ /// > square_root(4.0)
+ /// Ok(2.0)
+ ///
+ /// > square_root(-16.0)
+ /// Error(Nil)
+ ///
+ pub fn square_root(number: Float) -> Result(Float, Nil) {
+ case number <. 0.0 {
+ True -> Error(Nil)
+ False -> Ok(power(number, 0.5))
+ }
}
-}
-/// Returns the negative of the value provided
-///
-/// ## Examples
-///
-/// > negate(1.)
-/// -1.
-///
-pub fn negate(x: Float) -> Float {
- -1. *. x
-}
+ /// Returns the negative of the value provided
+ ///
+ /// ## Examples
+ ///
+ /// > negate(1.)
+ /// -1.
+ ///
+ pub fn negate(x: Float) -> Float {
+ -1. *. x
+ }
-/// Sums a list of Floats.
-///
-/// ## Example
-///
-/// > sum([1.0, 2.2, 3.3])
-/// 6.5
-///
-pub fn sum(numbers: List(Float)) -> Float {
- numbers
- |> do_sum(0.0)
-}
+ /// Sums a list of Floats.
+ ///
+ /// ## Example
+ ///
+ /// > sum([1.0, 2.2, 3.3])
+ /// 6.5
+ ///
+ pub fn sum(numbers: List(Float)) -> Float {
+ numbers
+ |> do_sum(0.0)
+ }
-fn do_sum(numbers: List(Float), initial: Float) -> Float {
- case numbers {
- [] -> initial
- [x, ..rest] -> do_sum(rest, x +. initial)
+ fn do_sum(numbers: List(Float), initial: Float) -> Float {
+ case numbers {
+ [] -> initial
+ [x, ..rest] -> do_sum(rest, x +. initial)
+ }
}
-}
-/// Multiplies a list of Floats and returns the product.
-///
-/// ## Example
-///
-/// > product([2.5, 3.2, 4.2])
-/// 33.6
-///
-pub fn product(numbers: List(Float)) -> Float {
- case numbers {
- [] -> 0.
- _ -> do_product(numbers, 1.)
+ /// Multiplies a list of Floats and returns the product.
+ ///
+ /// ## Example
+ ///
+ /// > product([2.5, 3.2, 4.2])
+ /// 33.6
+ ///
+ pub fn product(numbers: List(Float)) -> Float {
+ case numbers {
+ [] -> 0.
+ _ -> do_product(numbers, 1.)
+ }
}
-}
-fn do_product(numbers: List(Float), initial: Float) -> Float {
- case numbers {
- [] -> initial
- [x, ..rest] -> do_product(rest, x *. initial)
+ fn do_product(numbers: List(Float), initial: Float) -> Float {
+ case numbers {
+ [] -> initial
+ [x, ..rest] -> do_product(rest, x *. initial)
+ }
}
}
diff --git a/src/gleam/function.gleam b/src/gleam/function.gleam
index 08e7efd..937a9bc 100644
--- a/src/gleam/function.gleam
+++ b/src/gleam/function.gleam
@@ -1,71 +1,73 @@
-import gleam/dynamic.{Dynamic}
+if erlang {
+ import gleam/dynamic.{Dynamic}
-/// 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 {
- fn(a) { fun2(fun1(a)) }
-}
+ /// 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 {
+ fn(a) { fun2(fun1(a)) }
+ }
-/// Takes a function with arity two
-/// and returns a curried equivalent.
-/// fn(a, b) -> c becomes fn(a) -> fn(b) -> c
-pub fn curry2(fun: fn(a, b) -> value) {
- fn(a) { fn(b) { fun(a, b) } }
-}
+ /// Takes a function with arity two
+ /// and returns a curried equivalent.
+ /// fn(a, b) -> c becomes fn(a) -> fn(b) -> c
+ pub fn curry2(fun: fn(a, b) -> value) {
+ fn(a) { fn(b) { fun(a, b) } }
+ }
-/// Takes a function with arity three
-/// and returns a curried equivalent.
-/// fn(a, b, c) -> d becomes fn(a) -> fn(b) -> fn(c) -> d
-pub fn curry3(fun: fn(a, b, c) -> value) {
- fn(a) { fn(b) { fn(c) { fun(a, b, c) } } }
-}
+ /// Takes a function with arity three
+ /// and returns a curried equivalent.
+ /// fn(a, b, c) -> d becomes fn(a) -> fn(b) -> fn(c) -> d
+ pub fn curry3(fun: fn(a, b, c) -> value) {
+ fn(a) { fn(b) { fn(c) { fun(a, b, c) } } }
+ }
-/// Takes a function with arity four
-/// and returns a curried equivalent.
-pub fn curry4(fun: fn(a, b, c, d) -> value) {
- fn(a) { fn(b) { fn(c) { fn(d) { fun(a, b, c, d) } } } }
-}
+ /// Takes a function with arity four
+ /// and returns a curried equivalent.
+ pub fn curry4(fun: fn(a, b, c, d) -> value) {
+ fn(a) { fn(b) { fn(c) { fn(d) { fun(a, b, c, d) } } } }
+ }
-/// Takes a function with arity five
-/// and returns a curried equivalent.
-pub fn curry5(fun: fn(a, b, c, d, e) -> value) {
- fn(a) { fn(b) { fn(c) { fn(d) { fn(e) { fun(a, b, c, d, e) } } } } }
-}
+ /// Takes a function with arity five
+ /// and returns a curried equivalent.
+ pub fn curry5(fun: fn(a, b, c, d, e) -> value) {
+ fn(a) { fn(b) { fn(c) { fn(d) { fn(e) { fun(a, b, c, d, e) } } } } }
+ }
-/// Takes a function with arity six
-/// and returns a curried equivalent.
-pub fn curry6(fun: fn(a, b, c, d, e, f) -> value) {
- fn(a) {
- fn(b) { fn(c) { fn(d) { fn(e) { fn(f) { fun(a, b, c, d, e, f) } } } } }
+ /// Takes a function with arity six
+ /// and returns a curried equivalent.
+ pub fn curry6(fun: fn(a, b, c, d, e, f) -> value) {
+ fn(a) {
+ fn(b) { fn(c) { fn(d) { fn(e) { fn(f) { fun(a, b, c, d, e, f) } } } } }
+ }
}
-}
-/// Takes a function that takes two arguments and returns a new function that
-/// takes the same two arguments, but in reverse order.
-///
-pub fn flip(fun: fn(a, b) -> c) -> fn(b, a) -> c {
- fn(b, a) { fun(a, b) }
-}
+ /// Takes a function that takes two arguments and returns a new function that
+ /// takes the same two arguments, but in reverse order.
+ ///
+ pub fn flip(fun: fn(a, b) -> c) -> fn(b, a) -> c {
+ fn(b, a) { fun(a, b) }
+ }
-/// A function that always returns its input value.
-///
-pub fn identity(x: a) -> a {
- x
-}
+ /// A function that always returns its input value.
+ ///
+ pub fn identity(x: a) -> a {
+ x
+ }
-pub type Exception {
- Exited(Dynamic)
- Thrown(Dynamic)
- Errored(Dynamic)
-}
+ pub type Exception {
+ Exited(Dynamic)
+ Thrown(Dynamic)
+ Errored(Dynamic)
+ }
-/// Gleam doesn't offer any way to raise exceptions, but they may still occur
-/// due to bugs when working with unsafe code, such as when calling Erlang
-/// function.
-///
-/// This function will catch any error thrown and convert it into a result
-/// rather than crashing the process.
-///
-pub external fn rescue(fn() -> a) -> Result(a, Exception) =
- "gleam_stdlib" "rescue"
+ /// Gleam doesn't offer any way to raise exceptions, but they may still occur
+ /// due to bugs when working with unsafe code, such as when calling Erlang
+ /// function.
+ ///
+ /// This function will catch any error thrown and convert it into a result
+ /// rather than crashing the process.
+ ///
+ pub external fn rescue(fn() -> a) -> Result(a, Exception) =
+ "gleam_stdlib" "rescue"
+}
diff --git a/src/gleam/int.gleam b/src/gleam/int.gleam
index b77500c..b65d3a3 100644
--- a/src/gleam/int.gleam
+++ b/src/gleam/int.gleam
@@ -1,222 +1,224 @@
-import gleam/order.{Order}
-
-pub type Int =
- Int
-
-/// Returns the absolute value of the input.
-///
-/// ## Examples
-///
-/// > absolute_value(-12)
-/// 12
-///
-/// > absolute_value(10)
-/// 10
-///
-pub fn absolute_value(num: Int) -> Int {
- case num >= 0 {
- True -> num
- False -> num * -1
+if erlang {
+ import gleam/order.{Order}
+
+ pub type Int =
+ Int
+
+ /// Returns the absolute value of the input.
+ ///
+ /// ## Examples
+ ///
+ /// > absolute_value(-12)
+ /// 12
+ ///
+ /// > absolute_value(10)
+ /// 10
+ ///
+ pub fn absolute_value(num: Int) -> Int {
+ case num >= 0 {
+ True -> num
+ False -> num * -1
+ }
}
-}
-/// Parses a given string as an int if possible.
-///
-/// ## Examples
-///
-/// > parse("2")
-/// Ok(2)
-///
-/// > parse("ABC")
-/// Error(Nil)
-///
-pub external fn parse(String) -> Result(Int, Nil) =
- "gleam_stdlib" "parse_int"
-
-/// Prints a given int to a string.
-///
-/// ## Examples
-///
-/// > to_string(2)
-/// "2"
-///
-pub external fn to_string(Int) -> String =
- "erlang" "integer_to_binary"
-
-/// Prints a given int to a string using the base number provided.
-///
-/// ## Examples
-///
-/// > 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"
-
-/// Takes an int and returns its value as a float
-///
-/// ## Examples
-///
-/// > to_float(5)
-/// 5.
-///
-/// > to_float(0)
-/// 0.
-///
-/// > to_float(-3)
-/// -3.
-///
-pub external fn to_float(a: Int) -> Float =
- "erlang" "float"
-
-/// Restricts an Int between a lower and upper bound
-///
-/// ## Examples
-///
-/// ```
-/// > clamp(40, min: 50, max: 60)
-/// 50
-/// ```
-///
-pub fn clamp(n: Int, min min_bound: Int, max max_bound: Int) -> Int {
- n
- |> min(max_bound)
- |> max(min_bound)
-}
+ /// Parses a given string as an int if possible.
+ ///
+ /// ## Examples
+ ///
+ /// > parse("2")
+ /// Ok(2)
+ ///
+ /// > parse("ABC")
+ /// Error(Nil)
+ ///
+ pub external fn parse(String) -> Result(Int, Nil) =
+ "gleam_stdlib" "parse_int"
+
+ /// Prints a given int to a string.
+ ///
+ /// ## Examples
+ ///
+ /// > to_string(2)
+ /// "2"
+ ///
+ pub external fn to_string(Int) -> String =
+ "erlang" "integer_to_binary"
+
+ /// Prints a given int to a string using the base number provided.
+ ///
+ /// ## Examples
+ ///
+ /// > 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"
+
+ /// Takes an int and returns its value as a float
+ ///
+ /// ## Examples
+ ///
+ /// > to_float(5)
+ /// 5.
+ ///
+ /// > to_float(0)
+ /// 0.
+ ///
+ /// > to_float(-3)
+ /// -3.
+ ///
+ pub external fn to_float(a: Int) -> Float =
+ "erlang" "float"
+
+ /// Restricts an Int between a lower and upper bound
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > clamp(40, min: 50, max: 60)
+ /// 50
+ /// ```
+ ///
+ pub fn clamp(n: Int, min min_bound: Int, max max_bound: Int) -> Int {
+ n
+ |> min(max_bound)
+ |> max(min_bound)
+ }
-/// Compares two ints, returning an order.
-///
-/// ## Examples
-///
-/// > compare(2, 3)
-/// Lt
-///
-/// > compare(4, 3)
-/// Gt
-///
-/// > compare(3, 3)
-/// Eq
-///
-pub fn compare(a: Int, with b: Int) -> Order {
- case a == b {
- True -> order.Eq
- False ->
- case a < b {
- True -> order.Lt
- False -> order.Gt
- }
+ /// Compares two ints, returning an order.
+ ///
+ /// ## Examples
+ ///
+ /// > compare(2, 3)
+ /// Lt
+ ///
+ /// > compare(4, 3)
+ /// Gt
+ ///
+ /// > compare(3, 3)
+ /// Eq
+ ///
+ pub fn compare(a: Int, with b: Int) -> Order {
+ case a == b {
+ True -> order.Eq
+ False ->
+ case a < b {
+ True -> order.Lt
+ False -> order.Gt
+ }
+ }
}
-}
-/// Compares two int, returning the smaller of the two.
-///
-/// ## Examples
-///
-/// > min(2, 3)
-/// 2
-///
-pub fn min(a: Int, b: Int) -> Int {
- case a < b {
- True -> a
- False -> b
+ /// Compares two int, returning the smaller of the two.
+ ///
+ /// ## Examples
+ ///
+ /// > min(2, 3)
+ /// 2
+ ///
+ pub fn min(a: Int, b: Int) -> Int {
+ case a < b {
+ True -> a
+ False -> b
+ }
}
-}
-/// Compares two int, returning the larger of the two.
-///
-/// ## Examples
-///
-/// > max(2, 3)
-/// 3
-///
-pub fn max(a: Int, b: Int) -> Int {
- case a > b {
- True -> a
- False -> b
+ /// Compares two int, returning the larger of the two.
+ ///
+ /// ## Examples
+ ///
+ /// > max(2, 3)
+ /// 3
+ ///
+ pub fn max(a: Int, b: Int) -> Int {
+ case a > b {
+ True -> a
+ False -> b
+ }
}
-}
-/// Returns whether the value provided is even.
-///
-/// ## Examples
-///
-/// > is_even(2)
-/// True
-///
-/// > is_even(3)
-/// False
-///
-pub fn is_even(x: Int) -> Bool {
- x % 2 == 0
-}
+ /// Returns whether the value provided is even.
+ ///
+ /// ## Examples
+ ///
+ /// > 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
-///
-/// > is_odd(3)
-/// True
-///
-/// > is_odd(2)
-/// False
-///
-pub fn is_odd(x: Int) -> Bool {
- x % 2 != 0
-}
+ /// Returns whether the value provided is odd.
+ ///
+ /// ## Examples
+ ///
+ /// > is_odd(3)
+ /// True
+ ///
+ /// > is_odd(2)
+ /// False
+ ///
+ pub fn is_odd(x: Int) -> Bool {
+ x % 2 != 0
+ }
-/// Returns the negative of the value provided
-///
-/// ## Examples
-///
-/// > negate(1)
-/// -1
-///
-pub fn negate(x: Int) -> Int {
- -1 * x
-}
+ /// Returns the negative of the value provided
+ ///
+ /// ## Examples
+ ///
+ /// > negate(1)
+ /// -1
+ ///
+ pub fn negate(x: Int) -> Int {
+ -1 * x
+ }
-/// Sums a list of Ints.
-///
-/// ## Example
-///
-/// > sum([1, 2, 3])
-/// 6
-///
-pub fn sum(numbers: List(Int)) -> Int {
- numbers
- |> do_sum(0)
-}
+ /// Sums a list of Ints.
+ ///
+ /// ## Example
+ ///
+ /// > sum([1, 2, 3])
+ /// 6
+ ///
+ pub fn sum(numbers: List(Int)) -> Int {
+ numbers
+ |> do_sum(0)
+ }
-fn do_sum(numbers: List(Int), initial: Int) -> Int {
- case numbers {
- [] -> initial
- [x, ..rest] -> do_sum(rest, x + initial)
+ fn do_sum(numbers: List(Int), initial: Int) -> Int {
+ case numbers {
+ [] -> initial
+ [x, ..rest] -> do_sum(rest, x + initial)
+ }
}
-}
-/// Multiplies a list of Ints and returns the product.
-///
-/// ## Example
-///
-/// > product([2, 3, 4])
-/// 24
-///
-pub fn product(numbers: List(Int)) -> Int {
- case numbers {
- [] -> 0
- _ -> do_product(numbers, 1)
+ /// Multiplies a list of Ints and returns the product.
+ ///
+ /// ## Example
+ ///
+ /// > product([2, 3, 4])
+ /// 24
+ ///
+ pub fn product(numbers: List(Int)) -> Int {
+ case numbers {
+ [] -> 0
+ _ -> do_product(numbers, 1)
+ }
}
-}
-fn do_product(numbers: List(Int), initial: Int) -> Int {
- case numbers {
- [] -> initial
- [x, ..rest] -> do_product(rest, x * initial)
+ fn do_product(numbers: List(Int), initial: Int) -> Int {
+ case numbers {
+ [] -> initial
+ [x, ..rest] -> do_product(rest, x * initial)
+ }
}
}
diff --git a/src/gleam/io.gleam b/src/gleam/io.gleam
index a5b37df..f6e7f40 100644
--- a/src/gleam/io.gleam
+++ b/src/gleam/io.gleam
@@ -1,75 +1,77 @@
-external type DoNotLeak
+if erlang {
+ external type DoNotLeak
-external fn erl_print(String, List(a)) -> DoNotLeak =
- "io" "fwrite"
+ external fn erl_print(String, List(a)) -> DoNotLeak =
+ "io" "fwrite"
-/// Writes a string to standard output.
-///
-/// ## Example
-///
-/// > io.print("Hi mum")
-/// // -> Hi mum
-/// Nil
-///
-pub fn print(string: String) -> Nil {
- erl_print(string, [])
- Nil
-}
+ /// Writes a string to standard output.
+ ///
+ /// ## Example
+ ///
+ /// > io.print("Hi mum")
+ /// // -> Hi mum
+ /// Nil
+ ///
+ pub fn print(string: String) -> Nil {
+ erl_print(string, [])
+ Nil
+ }
-/// Writes a string to standard output, appending a newline to the end.
-///
-/// ## Example
-///
-/// > io.println("Hi mum")
-/// // -> Hi mum
-/// Nil
-///
-pub fn println(string: String) -> Nil {
- erl_print("~ts\n", [string])
- Nil
-}
+ /// Writes a string to standard output, appending a newline to the end.
+ ///
+ /// ## Example
+ ///
+ /// > io.println("Hi mum")
+ /// // -> Hi mum
+ /// Nil
+ ///
+ pub fn println(string: String) -> Nil {
+ erl_print("~ts\n", [string])
+ Nil
+ }
-/// Prints a value to standard output using Erlang syntax.
-///
-/// The value is returned after being printed so it can be used in pipelines.
-///
-/// ## Example
-///
-/// > io.debug("Hi mum")
-/// // -> <<"Hi mum">>
-/// "Hi mum"
-///
-/// > io.debug(Ok(1))
-/// // -> {ok, 1}
-/// Ok(1)
-///
-/// > import list
-/// > [1, 2]
-/// > |> list.map(fn(x) { x + 1 })
-/// > |> io.debug
-/// > |> list.map(fn(x) { x * 2 })
-/// // -> [2, 3]
-/// [4, 6]
-///
-pub fn debug(term: anything) -> anything {
- erl_print("~tp\n", [term])
- term
-}
+ /// Prints a value to standard output using Erlang syntax.
+ ///
+ /// The value is returned after being printed so it can be used in pipelines.
+ ///
+ /// ## Example
+ ///
+ /// > io.debug("Hi mum")
+ /// // -> <<"Hi mum">>
+ /// "Hi mum"
+ ///
+ /// > io.debug(Ok(1))
+ /// // -> {ok, 1}
+ /// Ok(1)
+ ///
+ /// > import list
+ /// > [1, 2]
+ /// > |> list.map(fn(x) { x + 1 })
+ /// > |> io.debug
+ /// > |> list.map(fn(x) { x * 2 })
+ /// // -> [2, 3]
+ /// [4, 6]
+ ///
+ pub fn debug(term: anything) -> anything {
+ erl_print("~tp\n", [term])
+ term
+ }
-/// Error value returned by `get_line` function
-///
-pub type GetLineError {
- Eof
- NoData
-}
+ /// Error value returned by `get_line` function
+ ///
+ pub type GetLineError {
+ Eof
+ NoData
+ }
-/// Reads a line from standard input with the given prompt.
-///
-/// # Example
-///
-/// > io.get_line("Language: ")
-/// // -> Language: <- gleam
-/// Ok("gleam\n")
-///
-pub external fn get_line(prompt: String) -> Result(String, GetLineError) =
- "gleam_stdlib" "get_line"
+ /// Reads a line from standard input with the given prompt.
+ ///
+ /// # Example
+ ///
+ /// > io.get_line("Language: ")
+ /// // -> Language: <- gleam
+ /// Ok("gleam\n")
+ ///
+ pub external fn get_line(prompt: String) -> Result(String, GetLineError) =
+ "gleam_stdlib" "get_line"
+}
diff --git a/src/gleam/iterator.gleam b/src/gleam/iterator.gleam
index 1b347c4..ff2e020 100644
--- a/src/gleam/iterator.gleam
+++ b/src/gleam/iterator.gleam
@@ -1,1029 +1,1037 @@
-import gleam/list
-import gleam/map.{Map}
-
-// Internal private representation of an Iterator
-type Action(element) {
- Stop
- Continue(element, fn() -> Action(element))
-}
+if erlang {
+ import gleam/list
+ import gleam/map.{Map}
+
+ // Internal private representation of an Iterator
+ type Action(element) {
+ Stop
+ Continue(element, fn() -> Action(element))
+ }
-/// An iterator is a lazily evaluated sequence of element.
-///
-/// Iterators are useful when working with collections that are too large to
-/// fit in memory (or those that are infinite in size) as they only require the
-/// elements currently being processed to be in memory.
-///
-/// As a lazy data structure no work is done when an iterator is filters,
-/// mapped, etc, instead a new iterator is returned with these transformations
-/// applied to the stream. Once the stream has all the required transformations
-/// applied it can be evaluated using functions such as `fold` and `to_list`.
-///
-pub opaque type Iterator(element) {
- Iterator(continuation: fn() -> Action(element))
-}
+ /// An iterator is a lazily evaluated sequence of element.
+ ///
+ /// Iterators are useful when working with collections that are too large to
+ /// fit in memory (or those that are infinite in size) as they only require the
+ /// elements currently being processed to be in memory.
+ ///
+ /// As a lazy data structure no work is done when an iterator is filters,
+ /// mapped, etc, instead a new iterator is returned with these transformations
+ /// applied to the stream. Once the stream has all the required transformations
+ /// applied it can be evaluated using functions such as `fold` and `to_list`.
+ ///
+ pub opaque type Iterator(element) {
+ Iterator(continuation: fn() -> Action(element))
+ }
-// Public API for iteration
-pub type Step(element, accumulator) {
- Next(element: element, accumulator: accumulator)
- Done
-}
+ // Public API for iteration
+ pub type Step(element, accumulator) {
+ Next(element: element, accumulator: accumulator)
+ Done
+ }
-// Shortcut for an empty iterator.
-fn stop() -> Action(element) {
- Stop
-}
+ // Shortcut for an empty iterator.
+ fn stop() -> Action(element) {
+ Stop
+ }
-// Creating Iterators
-fn do_unfold(
- initial: acc,
- f: fn(acc) -> Step(element, acc),
-) -> fn() -> Action(element) {
- fn() {
- case f(initial) {
- Next(x, acc) -> Continue(x, do_unfold(acc, f))
- Done -> Stop
+ // Creating Iterators
+ fn do_unfold(
+ initial: acc,
+ f: fn(acc) -> Step(element, acc),
+ ) -> fn() -> Action(element) {
+ fn() {
+ case f(initial) {
+ Next(x, acc) -> Continue(x, do_unfold(acc, f))
+ Done -> Stop
+ }
}
}
-}
-/// Creates an iterator from a given function and accumulator.
-///
-/// The function is called on the accumulator and returns either `Done`,
-/// indicating the iterator has no more elements, or `Next` which contains a
-/// new element and accumulator. The element is yielded by the iterator and the
-/// new accumulator is used with the function to compute the next element in
-/// the sequence.
-///
-/// ## Examples
-///
-/// > unfold(from: 5, with: fn(n) {
-/// > case n {
-/// > 0 -> Done
-/// > n -> Next(element: n, accumulator: n - 1)
-/// > }
-/// > })
-/// > |> to_list
-/// [5, 4, 3, 2, 1]
-///
-pub fn unfold(
- from initial: acc,
- with f: fn(acc) -> Step(element, acc),
-) -> Iterator(element) {
- initial
- |> do_unfold(f)
- |> Iterator
-}
+ /// Creates an iterator from a given function and accumulator.
+ ///
+ /// The function is called on the accumulator and returns either `Done`,
+ /// indicating the iterator has no more elements, or `Next` which contains a
+ /// new element and accumulator. The element is yielded by the iterator and the
+ /// new accumulator is used with the function to compute the next element in
+ /// the sequence.
+ ///
+ /// ## Examples
+ ///
+ /// > unfold(from: 5, with: fn(n) {
+ /// > case n {
+ /// > 0 -> Done
+ /// > n -> Next(element: n, accumulator: n - 1)
+ /// > }
+ /// > })
+ /// > |> to_list
+ /// [5, 4, 3, 2, 1]
+ ///
+ pub fn unfold(
+ from initial: acc,
+ with f: fn(acc) -> Step(element, acc),
+ ) -> Iterator(element) {
+ initial
+ |> do_unfold(f)
+ |> Iterator
+ }
-// TODO: test
-/// Creates an iterator that yields values created by calling a given function
-/// repeatedly.
-///
-pub fn repeatedly(f: fn() -> element) -> Iterator(element) {
- unfold(Nil, fn(_) { Next(f(), Nil) })
-}
+ // TODO: test
+ /// Creates an iterator that yields values created by calling a given function
+ /// repeatedly.
+ ///
+ pub fn repeatedly(f: fn() -> element) -> Iterator(element) {
+ unfold(Nil, fn(_) { Next(f(), Nil) })
+ }
-/// Creates an iterator that returns the same value infinitely.
-///
-/// ## Examples
-///
-/// > repeat(10)
-/// > |> take(4)
-/// > |> to_list
-/// [10, 10, 10, 10]
-///
-pub fn repeat(x: element) -> Iterator(element) {
- repeatedly(fn() { x })
-}
+ /// Creates an iterator that returns the same value infinitely.
+ ///
+ /// ## Examples
+ ///
+ /// > repeat(10)
+ /// > |> take(4)
+ /// > |> to_list
+ /// [10, 10, 10, 10]
+ ///
+ pub fn repeat(x: element) -> Iterator(element) {
+ repeatedly(fn() { x })
+ }
-/// Creates an iterator that yields each element from the given list.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3, 4]) |> to_list
-/// [1, 2, 3, 4]
-///
-pub fn from_list(list: List(element)) -> Iterator(element) {
- let yield = fn(acc) {
- case acc {
- [] -> Done
- [head, ..tail] -> Next(head, tail)
+ /// Creates an iterator that yields each element from the given list.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3, 4]) |> to_list
+ /// [1, 2, 3, 4]
+ ///
+ pub fn from_list(list: List(element)) -> Iterator(element) {
+ let yield = fn(acc) {
+ case acc {
+ [] -> Done
+ [head, ..tail] -> Next(head, tail)
+ }
}
+ unfold(list, yield)
}
- unfold(list, yield)
-}
-// Consuming Iterators
-fn do_fold(
- continuation: fn() -> Action(e),
- f: fn(e, acc) -> acc,
- accumulator: acc,
-) -> acc {
- case continuation() {
- Continue(elem, next) -> do_fold(next, f, f(elem, accumulator))
- Stop -> accumulator
+ // Consuming Iterators
+ fn do_fold(
+ continuation: fn() -> Action(e),
+ f: fn(e, acc) -> acc,
+ accumulator: acc,
+ ) -> acc {
+ case continuation() {
+ Continue(elem, next) -> do_fold(next, f, f(elem, accumulator))
+ Stop -> accumulator
+ }
}
-}
-/// Reduces an iterator of elements into a single value by calling a given
-/// function on each element in turn.
-///
-/// If called on an iterator of infinite length then this function will never
-/// return.
-///
-/// If you do not care about the end value and only wish to evaluate the
-/// iterator for side effects consider using the `run` function instead.
-///
-/// ## Examples
-///
-/// > [1, 2, 3, 4]
-/// > |> from_list
-/// > |> fold(from: 0, with: fn(element, acc) { element + acc })
-/// 10
-///
-pub fn fold(
- over iterator: Iterator(e),
- from initial: acc,
- with f: fn(e, acc) -> acc,
-) -> acc {
- iterator.continuation
- |> do_fold(f, initial)
-}
-
-// TODO: test
-/// Evaluates all elements emitted by the given iterator. This function is useful for when
-/// you wish to trigger any side effects that would occur when evaluating
-/// the iterator.
-///
-pub fn run(iterator: Iterator(e)) -> Nil {
- fold(iterator, Nil, fn(_, _) { Nil })
-}
+ /// Reduces an iterator of elements into a single value by calling a given
+ /// function on each element in turn.
+ ///
+ /// If called on an iterator of infinite length then this function will never
+ /// return.
+ ///
+ /// If you do not care about the end value and only wish to evaluate the
+ /// iterator for side effects consider using the `run` function instead.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 3, 4]
+ /// > |> from_list
+ /// > |> fold(from: 0, with: fn(element, acc) { element + acc })
+ /// 10
+ ///
+ pub fn fold(
+ over iterator: Iterator(e),
+ from initial: acc,
+ with f: fn(e, acc) -> acc,
+ ) -> acc {
+ iterator.continuation
+ |> do_fold(f, initial)
+ }
-/// Evaluates an iterator and returns all the elements as a list.
-///
-/// If called on an iterator of infinite length then this function will never
-/// return.
-///
-/// ## Examples
-///
-/// > [1, 2, 3] |> from_list |> map(fn(x) { x * 2 }) |> to_list
-/// [2, 4, 6]
-///
-pub fn to_list(iterator: Iterator(element)) -> List(element) {
- iterator
- |> fold([], fn(e, acc) { [e, ..acc] })
- |> list.reverse
-}
+ // TODO: test
+ /// Evaluates all elements emitted by the given iterator. This function is useful for when
+ /// you wish to trigger any side effects that would occur when evaluating
+ /// the iterator.
+ ///
+ pub fn run(iterator: Iterator(e)) -> Nil {
+ fold(iterator, Nil, fn(_, _) { Nil })
+ }
-/// Eagerly accesses the first value of an interator, returning a `Next`
-/// that contains the first value and the rest of the iterator.
-///
-/// If called on an empty iterator, `Done` is returned.
-///
-/// ## Examples
-///
-/// > assert Next(head, tail) =
-/// > [1, 2, 3, 4]
-/// > |> from_list
-/// > |> step
-/// > head
-/// 1
-///
-/// > tail |> to_list
-/// [2, 3, 4]
-///
-/// > empty() |> step
-/// Done
-///
-pub fn step(iterator: Iterator(e)) -> Step(e, Iterator(e)) {
- case iterator.continuation() {
- Stop -> Done
- Continue(e, a) -> Next(e, Iterator(a))
+ /// Evaluates an iterator and returns all the elements as a list.
+ ///
+ /// If called on an iterator of infinite length then this function will never
+ /// return.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 3] |> from_list |> map(fn(x) { x * 2 }) |> to_list
+ /// [2, 4, 6]
+ ///
+ pub fn to_list(iterator: Iterator(element)) -> List(element) {
+ iterator
+ |> fold([], fn(e, acc) { [e, ..acc] })
+ |> list.reverse
}
-}
-fn do_take(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) {
- fn() {
- case desired > 0 {
- False -> Stop
- True ->
- case continuation() {
- Stop -> Stop
- Continue(e, next) -> Continue(e, do_take(next, desired - 1))
- }
+ /// Eagerly accesses the first value of an interator, returning a `Next`
+ /// that contains the first value and the rest of the iterator.
+ ///
+ /// If called on an empty iterator, `Done` is returned.
+ ///
+ /// ## Examples
+ ///
+ /// > assert Next(head, tail) =
+ /// > [1, 2, 3, 4]
+ /// > |> from_list
+ /// > |> step
+ /// > head
+ /// 1
+ ///
+ /// > tail |> to_list
+ /// [2, 3, 4]
+ ///
+ /// > empty() |> step
+ /// Done
+ ///
+ pub fn step(iterator: Iterator(e)) -> Step(e, Iterator(e)) {
+ case iterator.continuation() {
+ Stop -> Done
+ Continue(e, a) -> Next(e, Iterator(a))
}
}
-}
-
-/// Creates an iterator that only yields the first `desired` elements.
-///
-/// If the iterator does not have enough elements all of them are yielded.
-///
-/// ## Examples
-///
-/// > [1, 2, 3, 4, 5] |> from_list |> take(up_to: 3) |> to_list
-/// [1, 2, 3]
-///
-/// > [1, 2] |> from_list |> take(up_to: 3) |> to_list
-/// [1, 2]
-///
-pub fn take(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) {
- iterator.continuation
- |> do_take(desired)
- |> Iterator
-}
-fn do_drop(continuation: fn() -> Action(e), desired: Int) -> Action(e) {
- case continuation() {
- Stop -> Stop
- Continue(e, next) ->
+ fn do_take(continuation: fn() -> Action(e), desired: Int) -> fn() -> Action(e) {
+ fn() {
case desired > 0 {
- True -> do_drop(next, desired - 1)
- False -> Continue(e, next)
+ False -> Stop
+ True ->
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) -> Continue(e, do_take(next, desired - 1))
+ }
}
+ }
}
-}
-/// Evaluates and discards the first N elements in an iterator, returning a new
-/// iterator.
-///
-/// If the iterator does not have enough elements an empty iterator is
-/// returned.
-///
-/// This function does not evaluate the elements of the iterator, the
-/// computation is performed when the iterator is later run.
-///
-/// ## Examples
-///
-/// > [1, 2, 3, 4, 5] |> from_list |> drop(up_to: 3) |> to_list
-/// [4, 5]
-///
-/// > [1, 2] |> from_list |> drop(up_to: 3) |> to_list
-/// []
-///
-pub fn drop(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) {
- fn() { do_drop(iterator.continuation, desired) }
- |> Iterator
-}
+ /// Creates an iterator that only yields the first `desired` elements.
+ ///
+ /// If the iterator does not have enough elements all of them are yielded.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 3, 4, 5] |> from_list |> take(up_to: 3) |> to_list
+ /// [1, 2, 3]
+ ///
+ /// > [1, 2] |> from_list |> take(up_to: 3) |> to_list
+ /// [1, 2]
+ ///
+ pub fn take(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) {
+ iterator.continuation
+ |> do_take(desired)
+ |> Iterator
+ }
-fn do_map(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) {
- fn() {
+ fn do_drop(continuation: fn() -> Action(e), desired: Int) -> Action(e) {
case continuation() {
Stop -> Stop
- Continue(e, continuation) -> Continue(f(e), do_map(continuation, f))
+ Continue(e, next) ->
+ case desired > 0 {
+ True -> do_drop(next, desired - 1)
+ False -> Continue(e, next)
+ }
}
}
-}
-/// Creates an iterator from an existing iterator and a transformation function.
-///
-/// Each element in the new iterator will be the result of calling the given
-/// function on the elements in the given iterator.
-///
-/// This function does not evaluate the elements of the iterator, the
-/// computation is performed when the iterator is later run.
-///
-/// ## Examples
-///
-/// > [1, 2, 3] |> from_list |> map(fn(x) { x * 2 }) |> to_list
-/// [2, 4, 6]
-///
-pub fn map(over iterator: Iterator(a), with f: fn(a) -> b) -> Iterator(b) {
- iterator.continuation
- |> do_map(f)
- |> Iterator
-}
-
-fn do_append(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) {
- case first() {
- Continue(e, first) -> Continue(e, fn() { do_append(first, second) })
- Stop -> second()
+ /// Evaluates and discards the first N elements in an iterator, returning a new
+ /// iterator.
+ ///
+ /// If the iterator does not have enough elements an empty iterator is
+ /// returned.
+ ///
+ /// This function does not evaluate the elements of the iterator, the
+ /// computation is performed when the iterator is later run.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 3, 4, 5] |> from_list |> drop(up_to: 3) |> to_list
+ /// [4, 5]
+ ///
+ /// > [1, 2] |> from_list |> drop(up_to: 3) |> to_list
+ /// []
+ ///
+ pub fn drop(from iterator: Iterator(e), up_to desired: Int) -> Iterator(e) {
+ fn() { do_drop(iterator.continuation, desired) }
+ |> Iterator
}
-}
-/// Appends two iterators, producing a new iterator.
-///
-/// This function does not evaluate the elements of the iterators, the
-/// computation is performed when the resulting iterator is later run.
-///
-/// ## Examples
-///
-/// > [1, 2] |> from_list |> append([3, 4] |> from_list) |> to_list
-/// [1, 2, 3, 4]
-///
-pub fn append(to first: Iterator(a), suffix second: Iterator(a)) -> Iterator(a) {
- fn() { do_append(first.continuation, second.continuation) }
- |> Iterator
-}
-
-fn do_flatten(flattened: fn() -> Action(Iterator(a))) -> Action(a) {
- case flattened() {
- Stop -> Stop
- Continue(it, next_iterator) ->
- do_append(it.continuation, fn() { do_flatten(next_iterator) })
+ fn do_map(continuation: fn() -> Action(a), f: fn(a) -> b) -> fn() -> Action(b) {
+ fn() {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, continuation) -> Continue(f(e), do_map(continuation, f))
+ }
+ }
}
-}
-/// Flattens an iterator of iterators, creating a new iterator.
-///
-/// This function does not evaluate the elements of the iterator, the
-/// computation is performed when the iterator is later run.
-///
-/// ## Examples
-///
-/// > from_list([[1, 2], [3, 4]]) |> map(from_list) |> flatten |> to_list
-/// [1, 2, 3, 4]
-///
-pub fn flatten(iterator: Iterator(Iterator(a))) -> Iterator(a) {
- fn() { do_flatten(iterator.continuation) }
- |> Iterator
-}
-
-/// Creates an iterator from an existing iterator and a transformation function.
-///
-/// Each element in the new iterator will be the result of calling the given
-/// function on the elements in the given iterator and then flattening the
-/// results.
-///
-/// This function does not evaluate the elements of the iterator, the
-/// computation is performed when the iterator is later run.
-///
-/// ## Examples
-///
-/// > [1, 2] |> from_list |> flat_map(fn(x) { from_list([x, x + 1]) }) |> to_list
-/// [1, 2, 2, 3]
-///
-pub fn flat_map(
- over iterator: Iterator(a),
- with f: fn(a) -> Iterator(b),
-) -> Iterator(b) {
- iterator
- |> map(f)
- |> flatten
-}
-
-fn do_filter(
- continuation: fn() -> Action(e),
- predicate: fn(e) -> Bool,
-) -> Action(e) {
- case continuation() {
- Stop -> Stop
- Continue(e, iterator) ->
- case predicate(e) {
- True -> Continue(e, fn() { do_filter(iterator, predicate) })
- False -> do_filter(iterator, predicate)
- }
+ /// Creates an iterator from an existing iterator and a transformation function.
+ ///
+ /// Each element in the new iterator will be the result of calling the given
+ /// function on the elements in the given iterator.
+ ///
+ /// This function does not evaluate the elements of the iterator, the
+ /// computation is performed when the iterator is later run.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 3] |> from_list |> map(fn(x) { x * 2 }) |> to_list
+ /// [2, 4, 6]
+ ///
+ pub fn map(over iterator: Iterator(a), with f: fn(a) -> b) -> Iterator(b) {
+ iterator.continuation
+ |> do_map(f)
+ |> Iterator
}
-}
-/// Creates an iterator from an existing iterator and a predicate function.
-///
-/// The new iterator will contain elements from the first iterator for which
-/// the given function returns `True`.
-///
-/// This function does not evaluate the elements of the iterator, the
-/// computation is performed when the iterator is later run.
-///
-/// ## Examples
-///
-/// > import gleam/int
-/// > [1, 2, 3, 4] |> from_list |> filter(int.is_even) |> to_list
-/// [2, 4]
-///
-pub fn filter(
- iterator: Iterator(a),
- for predicate: fn(a) -> Bool,
-) -> Iterator(a) {
- fn() { do_filter(iterator.continuation, predicate) }
- |> Iterator
-}
+ fn do_append(first: fn() -> Action(a), second: fn() -> Action(a)) -> Action(a) {
+ case first() {
+ Continue(e, first) -> Continue(e, fn() { do_append(first, second) })
+ Stop -> second()
+ }
+ }
-/// Creates an iterator that repeats a given iterator infinitely.
-///
-/// ## Examples
-///
-/// > [1, 2] |> from_list |> cycle |> take(6)
-/// [1, 2, 1, 2, 1, 2]
-///
-pub fn cycle(iterator: Iterator(a)) -> Iterator(a) {
- repeat(iterator)
- |> flatten
-}
+ /// Appends two iterators, producing a new iterator.
+ ///
+ /// This function does not evaluate the elements of the iterators, the
+ /// computation is performed when the resulting iterator is later run.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2] |> from_list |> append([3, 4] |> from_list) |> to_list
+ /// [1, 2, 3, 4]
+ ///
+ pub fn append(
+ to first: Iterator(a),
+ suffix second: Iterator(a),
+ ) -> Iterator(a) {
+ fn() { do_append(first.continuation, second.continuation) }
+ |> Iterator
+ }
-/// Creates an iterator of ints, starting at a given start int and stepping by
-/// one to a given end int.
-///
-/// ## Examples
-///
-/// > range(from: 1, to: 5) |> to_list
-/// [1, 2, 3, 4]
-///
-/// > range(from: 1, to: -2) |> to_list
-/// [1, 0, -1]
-///
-/// > range(from: 0, to: 0) |> to_list
-/// []
-///
-pub fn range(from start: Int, to stop: Int) -> Iterator(Int) {
- let increment = case start < stop {
- True -> 1
- False -> -1
- }
-
- let next_step = fn(current) {
- case current == stop {
- True -> Done
- False -> Next(current, current + increment)
+ fn do_flatten(flattened: fn() -> Action(Iterator(a))) -> Action(a) {
+ case flattened() {
+ Stop -> Stop
+ Continue(it, next_iterator) ->
+ do_append(it.continuation, fn() { do_flatten(next_iterator) })
}
}
- unfold(start, next_step)
-}
-
-fn do_find(continuation: fn() -> Action(a), f: fn(a) -> Bool) -> Result(a, Nil) {
- case continuation() {
- Stop -> Error(Nil)
- Continue(e, next) ->
- case f(e) {
- True -> Ok(e)
- False -> do_find(next, f)
- }
+ /// Flattens an iterator of iterators, creating a new iterator.
+ ///
+ /// This function does not evaluate the elements of the iterator, the
+ /// computation is performed when the iterator is later run.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([[1, 2], [3, 4]]) |> map(from_list) |> flatten |> to_list
+ /// [1, 2, 3, 4]
+ ///
+ pub fn flatten(iterator: Iterator(Iterator(a))) -> Iterator(a) {
+ fn() { do_flatten(iterator.continuation) }
+ |> Iterator
}
-}
-/// Finds the first element in a given iterator for which the given function returns
-/// True.
-///
-/// Returns `Error(Nil)` if the function does not return True for any of the
-/// elements.
-///
-/// ## Examples
-///
-/// > find(from_list([1, 2, 3]), fn(x) { x > 2 })
-/// Ok(3)
-///
-/// > find(from_list([1, 2, 3]), fn(x) { x > 4 })
-/// Error(Nil)
-///
-/// > find(empty(), fn(x) { True })
-/// Error(Nil)
-///
-pub fn find(
- in haystack: Iterator(a),
- one_that is_desired: fn(a) -> Bool,
-) -> Result(a, Nil) {
- haystack.continuation
- |> do_find(is_desired)
-}
+ /// Creates an iterator from an existing iterator and a transformation function.
+ ///
+ /// Each element in the new iterator will be the result of calling the given
+ /// function on the elements in the given iterator and then flattening the
+ /// results.
+ ///
+ /// This function does not evaluate the elements of the iterator, the
+ /// computation is performed when the iterator is later run.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2] |> from_list |> flat_map(fn(x) { from_list([x, x + 1]) }) |> to_list
+ /// [1, 2, 2, 3]
+ ///
+ pub fn flat_map(
+ over iterator: Iterator(a),
+ with f: fn(a) -> Iterator(b),
+ ) -> Iterator(b) {
+ iterator
+ |> map(f)
+ |> flatten
+ }
-fn do_index(
- continuation: fn() -> Action(element),
- next: Int,
-) -> fn() -> Action(#(Int, element)) {
- fn() {
+ fn do_filter(
+ continuation: fn() -> Action(e),
+ predicate: fn(e) -> Bool,
+ ) -> Action(e) {
case continuation() {
Stop -> Stop
- Continue(e, continuation) ->
- Continue(#(next, e), do_index(continuation, next + 1))
+ Continue(e, iterator) ->
+ case predicate(e) {
+ True -> Continue(e, fn() { do_filter(iterator, predicate) })
+ False -> do_filter(iterator, predicate)
+ }
}
}
-}
-/// Wraps values yielded from an iterator with indices, starting from 0.
-///
-/// ## Examples
-///
-/// > from_list(["a", "b", "c"]) |> index |> to_list
-/// [#(0, "a"), #(1, "b"), #(2, "c")]
-///
-pub fn index(over iterator: Iterator(element)) -> Iterator(#(Int, element)) {
- iterator.continuation
- |> do_index(0)
- |> Iterator
-}
+ /// Creates an iterator from an existing iterator and a predicate function.
+ ///
+ /// The new iterator will contain elements from the first iterator for which
+ /// the given function returns `True`.
+ ///
+ /// This function does not evaluate the elements of the iterator, the
+ /// computation is performed when the iterator is later run.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/int
+ /// > [1, 2, 3, 4] |> from_list |> filter(int.is_even) |> to_list
+ /// [2, 4]
+ ///
+ pub fn filter(
+ iterator: Iterator(a),
+ for predicate: fn(a) -> Bool,
+ ) -> Iterator(a) {
+ fn() { do_filter(iterator.continuation, predicate) }
+ |> Iterator
+ }
-/// Creates an iterator that inifinitely applies a function to a value.
-///
-/// ## Examples
-///
-/// > iterate(1, fn(n) { n * 3 }) |> take(5)
-/// [1, 3, 9, 27, 81]
-///
-pub fn iterate(
- from initial: element,
- with f: fn(element) -> element,
-) -> Iterator(element) {
- unfold(initial, fn(element) { Next(element, f(element)) })
-}
+ /// Creates an iterator that repeats a given iterator infinitely.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2] |> from_list |> cycle |> take(6)
+ /// [1, 2, 1, 2, 1, 2]
+ ///
+ pub fn cycle(iterator: Iterator(a)) -> Iterator(a) {
+ repeat(iterator)
+ |> flatten
+ }
+
+ /// Creates an iterator of ints, starting at a given start int and stepping by
+ /// one to a given end int.
+ ///
+ /// ## Examples
+ ///
+ /// > range(from: 1, to: 5) |> to_list
+ /// [1, 2, 3, 4]
+ ///
+ /// > range(from: 1, to: -2) |> to_list
+ /// [1, 0, -1]
+ ///
+ /// > range(from: 0, to: 0) |> to_list
+ /// []
+ ///
+ pub fn range(from start: Int, to stop: Int) -> Iterator(Int) {
+ let increment = case start < stop {
+ True -> 1
+ False -> -1
+ }
+
+ let next_step = fn(current) {
+ case current == stop {
+ True -> Done
+ False -> Next(current, current + increment)
+ }
+ }
+
+ unfold(start, next_step)
+ }
-fn do_take_while(
- continuation: fn() -> Action(element),
- predicate: fn(element) -> Bool,
-) -> fn() -> Action(element) {
- fn() {
+ fn do_find(
+ continuation: fn() -> Action(a),
+ f: fn(a) -> Bool,
+ ) -> Result(a, Nil) {
case continuation() {
- Stop -> Stop
+ Stop -> Error(Nil)
Continue(e, next) ->
- case predicate(e) {
- False -> Stop
- True -> Continue(e, do_take_while(next, predicate))
+ case f(e) {
+ True -> Ok(e)
+ False -> do_find(next, f)
}
}
}
-}
-/// Creates an iterator that yields elements while the predicate returns `True`.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3, 2, 4]) |> take_while(satisfying: fn(x) { x < 3 }) |> to_list
-/// [1, 2]
-///
-pub fn take_while(
- in iterator: Iterator(element),
- satisfying predicate: fn(element) -> Bool,
-) -> Iterator(element) {
- iterator.continuation
- |> do_take_while(predicate)
- |> Iterator
-}
+ /// Finds the first element in a given iterator for which the given function returns
+ /// True.
+ ///
+ /// Returns `Error(Nil)` if the function does not return True for any of the
+ /// elements.
+ ///
+ /// ## Examples
+ ///
+ /// > find(from_list([1, 2, 3]), fn(x) { x > 2 })
+ /// Ok(3)
+ ///
+ /// > find(from_list([1, 2, 3]), fn(x) { x > 4 })
+ /// Error(Nil)
+ ///
+ /// > find(empty(), fn(x) { True })
+ /// Error(Nil)
+ ///
+ pub fn find(
+ in haystack: Iterator(a),
+ one_that is_desired: fn(a) -> Bool,
+ ) -> Result(a, Nil) {
+ haystack.continuation
+ |> do_find(is_desired)
+ }
-fn do_drop_while(
- continuation: fn() -> Action(element),
- predicate: fn(element) -> Bool,
-) -> Action(element) {
- case continuation() {
- Stop -> Stop
- Continue(e, next) ->
- case predicate(e) {
- False -> Continue(e, next)
- True -> do_drop_while(next, predicate)
+ fn do_index(
+ continuation: fn() -> Action(element),
+ next: Int,
+ ) -> fn() -> Action(#(Int, element)) {
+ fn() {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, continuation) ->
+ Continue(#(next, e), do_index(continuation, next + 1))
}
+ }
}
-}
-/// Creates an iterator that drops elements while the predicate returns `True`,
-/// and then yields the remaining elements.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3, 4, 2, 5]) |> drop_while(satisfying: fn(x) { x < 4 }) |> to_list
-/// [4, 2, 5]
-///
-pub fn drop_while(
- in iterator: Iterator(element),
- satisfying predicate: fn(element) -> Bool,
-) -> Iterator(element) {
- fn() { do_drop_while(iterator.continuation, predicate) }
- |> Iterator
-}
+ /// Wraps values yielded from an iterator with indices, starting from 0.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list(["a", "b", "c"]) |> index |> to_list
+ /// [#(0, "a"), #(1, "b"), #(2, "c")]
+ ///
+ pub fn index(over iterator: Iterator(element)) -> Iterator(#(Int, element)) {
+ iterator.continuation
+ |> do_index(0)
+ |> Iterator
+ }
-fn do_scan(
- continuation: fn() -> Action(element),
- f: fn(element, acc) -> acc,
- accumulator: acc,
-) -> fn() -> Action(acc) {
- fn() {
- case continuation() {
- Stop -> Stop
- Continue(el, next) -> {
- let accumulated = f(el, accumulator)
- Continue(accumulated, do_scan(next, f, accumulated))
+ /// Creates an iterator that inifinitely applies a function to a value.
+ ///
+ /// ## Examples
+ ///
+ /// > iterate(1, fn(n) { n * 3 }) |> take(5)
+ /// [1, 3, 9, 27, 81]
+ ///
+ pub fn iterate(
+ from initial: element,
+ with f: fn(element) -> element,
+ ) -> Iterator(element) {
+ unfold(initial, fn(element) { Next(element, f(element)) })
+ }
+
+ fn do_take_while(
+ continuation: fn() -> Action(element),
+ predicate: fn(element) -> Bool,
+ ) -> fn() -> Action(element) {
+ fn() {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) ->
+ case predicate(e) {
+ False -> Stop
+ True -> Continue(e, do_take_while(next, predicate))
+ }
}
}
}
-}
-/// Creates an iterator from an existing iterator and a stateful function.
-///
-/// Specifically, this behaves like `fold`, but yields intermediate results.
-///
-/// ## Examples
-///
-/// Generate a sequence of partial sums:
-/// > from_list([1, 2, 3, 4, 5]) |> scan(from: 0, with: fn(el, acc) { acc + el }) |> to_list
-/// [1, 3, 6, 10, 15]
-///
-pub fn scan(
- over iterator: Iterator(element),
- from initial: acc,
- with f: fn(element, acc) -> acc,
-) -> Iterator(acc) {
- iterator.continuation
- |> do_scan(f, initial)
- |> Iterator
-}
+ /// Creates an iterator that yields elements while the predicate returns `True`.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3, 2, 4]) |> take_while(satisfying: fn(x) { x < 3 }) |> to_list
+ /// [1, 2]
+ ///
+ pub fn take_while(
+ in iterator: Iterator(element),
+ satisfying predicate: fn(element) -> Bool,
+ ) -> Iterator(element) {
+ iterator.continuation
+ |> do_take_while(predicate)
+ |> Iterator
+ }
-fn do_zip(
- left: fn() -> Action(a),
- right: fn() -> Action(b),
-) -> fn() -> Action(#(a, b)) {
- fn() {
- case left() {
+ fn do_drop_while(
+ continuation: fn() -> Action(element),
+ predicate: fn(element) -> Bool,
+ ) -> Action(element) {
+ case continuation() {
Stop -> Stop
- Continue(el_left, next_left) ->
- case right() {
- Stop -> Stop
- Continue(el_right, next_right) ->
- Continue(#(el_left, el_right), do_zip(next_left, next_right))
+ Continue(e, next) ->
+ case predicate(e) {
+ False -> Continue(e, next)
+ True -> do_drop_while(next, predicate)
}
}
}
-}
-/// Zips two iterators together, emitting values from both
-/// until the shorter one runs out.
-///
-/// ## Examples
-///
-/// > from_list(["a", "b", "c"]) |> zip(range(20, 30)) |> to_list
-/// [#("a", 20), #("b", 21), #("c", 22)]
-///
-pub fn zip(left: Iterator(a), right: Iterator(b)) -> Iterator(#(a, b)) {
- do_zip(left.continuation, right.continuation)
- |> Iterator
-}
+ /// Creates an iterator that drops elements while the predicate returns `True`,
+ /// and then yields the remaining elements.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3, 4, 2, 5]) |> drop_while(satisfying: fn(x) { x < 4 }) |> to_list
+ /// [4, 2, 5]
+ ///
+ pub fn drop_while(
+ in iterator: Iterator(element),
+ satisfying predicate: fn(element) -> Bool,
+ ) -> Iterator(element) {
+ fn() { do_drop_while(iterator.continuation, predicate) }
+ |> Iterator
+ }
-// Result of collecting a single chunk by key
-type Chunk(element, key) {
- AnotherBy(List(element), key, element, fn() -> Action(element))
- LastBy(List(element))
-}
+ fn do_scan(
+ continuation: fn() -> Action(element),
+ f: fn(element, acc) -> acc,
+ accumulator: acc,
+ ) -> fn() -> Action(acc) {
+ fn() {
+ case continuation() {
+ Stop -> Stop
+ Continue(el, next) -> {
+ let accumulated = f(el, accumulator)
+ Continue(accumulated, do_scan(next, f, accumulated))
+ }
+ }
+ }
+ }
+
+ /// Creates an iterator from an existing iterator and a stateful function.
+ ///
+ /// Specifically, this behaves like `fold`, but yields intermediate results.
+ ///
+ /// ## Examples
+ ///
+ /// Generate a sequence of partial sums:
+ /// > from_list([1, 2, 3, 4, 5]) |> scan(from: 0, with: fn(el, acc) { acc + el }) |> to_list
+ /// [1, 3, 6, 10, 15]
+ ///
+ pub fn scan(
+ over iterator: Iterator(element),
+ from initial: acc,
+ with f: fn(element, acc) -> acc,
+ ) -> Iterator(acc) {
+ iterator.continuation
+ |> do_scan(f, initial)
+ |> Iterator
+ }
-fn next_chunk(
- continuation: fn() -> Action(element),
- f: fn(element) -> key,
- previous_key: key,
- current_chunk: List(element),
-) -> Chunk(element, key) {
- case continuation() {
- Stop -> LastBy(list.reverse(current_chunk))
- Continue(e, next) -> {
- let key = f(e)
- case key == previous_key {
- True -> next_chunk(next, f, key, [e, ..current_chunk])
- False -> AnotherBy(list.reverse(current_chunk), key, e, next)
+ fn do_zip(
+ left: fn() -> Action(a),
+ right: fn() -> Action(b),
+ ) -> fn() -> Action(#(a, b)) {
+ fn() {
+ case left() {
+ Stop -> Stop
+ Continue(el_left, next_left) ->
+ case right() {
+ Stop -> Stop
+ Continue(el_right, next_right) ->
+ Continue(#(el_left, el_right), do_zip(next_left, next_right))
+ }
}
}
}
-}
-fn do_chunk(
- continuation: fn() -> Action(element),
- f: fn(element) -> key,
- previous_key: key,
- previous_element: element,
-) -> Action(List(element)) {
- case next_chunk(continuation, f, previous_key, [previous_element]) {
- LastBy(chunk) -> Continue(chunk, stop)
- AnotherBy(chunk, key, el, next) ->
- Continue(chunk, fn() { do_chunk(next, f, key, el) })
+ /// Zips two iterators together, emitting values from both
+ /// until the shorter one runs out.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list(["a", "b", "c"]) |> zip(range(20, 30)) |> to_list
+ /// [#("a", 20), #("b", 21), #("c", 22)]
+ ///
+ pub fn zip(left: Iterator(a), right: Iterator(b)) -> Iterator(#(a, b)) {
+ do_zip(left.continuation, right.continuation)
+ |> Iterator
}
-}
-/// Creates an iterator that emits chunks of elements
-/// for which `f` returns the same value.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 2, 3, 4, 4, 6, 7, 7]) |> chunk(by: fn(n) { n % 2 }) |> to_list
-/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]]
-///
-pub fn chunk(
- over iterator: Iterator(element),
- by f: fn(element) -> key,
-) -> Iterator(List(element)) {
- fn() {
- case iterator.continuation() {
- Stop -> Stop
- Continue(e, next) -> do_chunk(next, f, f(e), e)
+ // Result of collecting a single chunk by key
+ type Chunk(element, key) {
+ AnotherBy(List(element), key, element, fn() -> Action(element))
+ LastBy(List(element))
+ }
+
+ fn next_chunk(
+ continuation: fn() -> Action(element),
+ f: fn(element) -> key,
+ previous_key: key,
+ current_chunk: List(element),
+ ) -> Chunk(element, key) {
+ case continuation() {
+ Stop -> LastBy(list.reverse(current_chunk))
+ Continue(e, next) -> {
+ let key = f(e)
+ case key == previous_key {
+ True -> next_chunk(next, f, key, [e, ..current_chunk])
+ False -> AnotherBy(list.reverse(current_chunk), key, e, next)
+ }
+ }
}
}
- |> Iterator
-}
-// Result of collecting a single sized chunk
-type SizedChunk(element) {
- Another(List(element), fn() -> Action(element))
- Last(List(element))
- None
-}
+ fn do_chunk(
+ continuation: fn() -> Action(element),
+ f: fn(element) -> key,
+ previous_key: key,
+ previous_element: element,
+ ) -> Action(List(element)) {
+ case next_chunk(continuation, f, previous_key, [previous_element]) {
+ LastBy(chunk) -> Continue(chunk, stop)
+ AnotherBy(chunk, key, el, next) ->
+ Continue(chunk, fn() { do_chunk(next, f, key, el) })
+ }
+ }
-fn next_sized_chunk(
- continuation: fn() -> Action(element),
- left: Int,
- current_chunk: List(element),
-) -> SizedChunk(element) {
- case continuation() {
- Stop ->
- case current_chunk {
- [] -> None
- remaining -> Last(list.reverse(remaining))
+ /// Creates an iterator that emits chunks of elements
+ /// for which `f` returns the same value.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 2, 3, 4, 4, 6, 7, 7]) |> chunk(by: fn(n) { n % 2 }) |> to_list
+ /// [[1], [2, 2], [3], [4, 4, 6], [7, 7]]
+ ///
+ pub fn chunk(
+ over iterator: Iterator(element),
+ by f: fn(element) -> key,
+ ) -> Iterator(List(element)) {
+ fn() {
+ case iterator.continuation() {
+ Stop -> Stop
+ Continue(e, next) -> do_chunk(next, f, f(e), e)
}
- Continue(e, next) -> {
- let chunk = [e, ..current_chunk]
- case left > 1 {
- False -> Another(list.reverse(chunk), next)
- True -> next_sized_chunk(next, left - 1, chunk)
+ }
+ |> Iterator
+ }
+
+ // Result of collecting a single sized chunk
+ type SizedChunk(element) {
+ Another(List(element), fn() -> Action(element))
+ Last(List(element))
+ None
+ }
+
+ fn next_sized_chunk(
+ continuation: fn() -> Action(element),
+ left: Int,
+ current_chunk: List(element),
+ ) -> SizedChunk(element) {
+ case continuation() {
+ Stop ->
+ case current_chunk {
+ [] -> None
+ remaining -> Last(list.reverse(remaining))
+ }
+ Continue(e, next) -> {
+ let chunk = [e, ..current_chunk]
+ case left > 1 {
+ False -> Another(list.reverse(chunk), next)
+ True -> next_sized_chunk(next, left - 1, chunk)
+ }
}
}
}
-}
-fn do_sized_chunk(
- continuation: fn() -> Action(element),
- count: Int,
-) -> fn() -> Action(List(element)) {
- fn() {
- case next_sized_chunk(continuation, count, []) {
- None -> Stop
- Last(chunk) -> Continue(chunk, stop)
- Another(chunk, next_element) ->
- Continue(chunk, do_sized_chunk(next_element, count))
+ fn do_sized_chunk(
+ continuation: fn() -> Action(element),
+ count: Int,
+ ) -> fn() -> Action(List(element)) {
+ fn() {
+ case next_sized_chunk(continuation, count, []) {
+ None -> Stop
+ Last(chunk) -> Continue(chunk, stop)
+ Another(chunk, next_element) ->
+ Continue(chunk, do_sized_chunk(next_element, count))
+ }
}
}
-}
-/// Creates an iterator that emits chunks of given size.
-///
-/// If the last chunk does not have `count` elements, it is yielded
-/// as a partial chunk, with less than `count` elements.
-///
-/// For any `count` less than 1 this function behaves as if it was set to 1.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3, 4, 5, 6]) |> chunk(into: 2) |> to_list
-/// [[1, 2], [3, 4], [5, 6]]
-///
-/// > from_list([1, 2, 3, 4, 5, 6, 7, 8]) |> chunk(into: 3) |> to_list
-/// [[1, 2, 3], [4, 5, 6], [7, 8]]
-///
-pub fn sized_chunk(
- over iterator: Iterator(element),
- into count: Int,
-) -> Iterator(List(element)) {
- iterator.continuation
- |> do_sized_chunk(count)
- |> Iterator
-}
+ /// Creates an iterator that emits chunks of given size.
+ ///
+ /// If the last chunk does not have `count` elements, it is yielded
+ /// as a partial chunk, with less than `count` elements.
+ ///
+ /// For any `count` less than 1 this function behaves as if it was set to 1.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3, 4, 5, 6]) |> chunk(into: 2) |> to_list
+ /// [[1, 2], [3, 4], [5, 6]]
+ ///
+ /// > from_list([1, 2, 3, 4, 5, 6, 7, 8]) |> chunk(into: 3) |> to_list
+ /// [[1, 2, 3], [4, 5, 6], [7, 8]]
+ ///
+ pub fn sized_chunk(
+ over iterator: Iterator(element),
+ into count: Int,
+ ) -> Iterator(List(element)) {
+ iterator.continuation
+ |> do_sized_chunk(count)
+ |> Iterator
+ }
-fn do_intersperse(
- continuation: fn() -> Action(element),
- separator: element,
-) -> Action(element) {
- case continuation() {
- Stop -> Stop
- Continue(e, next) -> {
- let next_interspersed = fn() { do_intersperse(next, separator) }
- Continue(separator, fn() { Continue(e, next_interspersed) })
+ fn do_intersperse(
+ continuation: fn() -> Action(element),
+ separator: element,
+ ) -> Action(element) {
+ case continuation() {
+ Stop -> Stop
+ Continue(e, next) -> {
+ let next_interspersed = fn() { do_intersperse(next, separator) }
+ Continue(separator, fn() { Continue(e, next_interspersed) })
+ }
}
}
-}
-/// Creates an iterator that yields the given element
-/// between elements emitted by the underlying iterator.
-///
-/// ## Examples
-///
-/// > empty() |> intersperse(with: 0) |> to_list
-/// []
-///
-/// > from_list([1]) |> intersperse(with: 0) |> to_list
-/// [1]
-///
-/// > from_list([1, 2, 3, 4, 5]) |> intersperse(with: 0) |> to_list
-/// [1, 0, 2, 0, 3, 0, 4, 0, 5]
-///
-pub fn intersperse(
- over iterator: Iterator(element),
- with elem: element,
-) -> Iterator(element) {
- fn() {
- case iterator.continuation() {
- Stop -> Stop
- Continue(e, next) -> Continue(e, fn() { do_intersperse(next, elem) })
+ /// Creates an iterator that yields the given element
+ /// between elements emitted by the underlying iterator.
+ ///
+ /// ## Examples
+ ///
+ /// > empty() |> intersperse(with: 0) |> to_list
+ /// []
+ ///
+ /// > from_list([1]) |> intersperse(with: 0) |> to_list
+ /// [1]
+ ///
+ /// > from_list([1, 2, 3, 4, 5]) |> intersperse(with: 0) |> to_list
+ /// [1, 0, 2, 0, 3, 0, 4, 0, 5]
+ ///
+ pub fn intersperse(
+ over iterator: Iterator(element),
+ with elem: element,
+ ) -> Iterator(element) {
+ fn() {
+ case iterator.continuation() {
+ Stop -> Stop
+ Continue(e, next) -> Continue(e, fn() { do_intersperse(next, elem) })
+ }
}
+ |> Iterator
}
- |> Iterator
-}
-fn do_any(
- continuation: fn() -> Action(element),
- predicate: fn(element) -> Bool,
-) -> Bool {
- case continuation() {
- Stop -> False
- Continue(e, next) -> predicate(e) || do_any(next, predicate)
+ fn do_any(
+ continuation: fn() -> Action(element),
+ predicate: fn(element) -> Bool,
+ ) -> Bool {
+ case continuation() {
+ Stop -> False
+ Continue(e, next) -> predicate(e) || do_any(next, predicate)
+ }
}
-}
-/// Returns `True` if any element emitted by the iterator satisfies the given predicate,
-/// `False` otherwise.
-///
-/// This function short-circuits once it finds a satisfying element.
-///
-/// An empty iterator results in `False`.
-///
-/// ## Examples
-///
-/// > empty() |> any(fn(n) { n % 2 == 0 })
-/// False
-///
-/// > from_list([1, 2, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 })
-/// True
-///
-/// > from_list([1, 3, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 })
-/// False
-///
-pub fn any(
- in iterator: Iterator(element),
- satisfying predicate: fn(element) -> Bool,
-) -> Bool {
- iterator.continuation
- |> do_any(predicate)
-}
+ /// Returns `True` if any element emitted by the iterator satisfies the given predicate,
+ /// `False` otherwise.
+ ///
+ /// This function short-circuits once it finds a satisfying element.
+ ///
+ /// An empty iterator results in `False`.
+ ///
+ /// ## Examples
+ ///
+ /// > empty() |> any(fn(n) { n % 2 == 0 })
+ /// False
+ ///
+ /// > from_list([1, 2, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 })
+ /// True
+ ///
+ /// > from_list([1, 3, 5, 7, 9]) |> any(fn(n) { n % 2 == 0 })
+ /// False
+ ///
+ pub fn any(
+ in iterator: Iterator(element),
+ satisfying predicate: fn(element) -> Bool,
+ ) -> Bool {
+ iterator.continuation
+ |> do_any(predicate)
+ }
-fn do_all(
- continuation: fn() -> Action(element),
- predicate: fn(element) -> Bool,
-) -> Bool {
- case continuation() {
- Stop -> True
- Continue(e, next) -> predicate(e) && do_all(next, predicate)
+ fn do_all(
+ continuation: fn() -> Action(element),
+ predicate: fn(element) -> Bool,
+ ) -> Bool {
+ case continuation() {
+ Stop -> True
+ Continue(e, next) -> predicate(e) && do_all(next, predicate)
+ }
}
-}
-/// Returns `True` if all elements emitted by the iterator satisfy the given predicate,
-/// `False` otherwise.
-///
-/// This function short-circuits once it finds a non-satisfying element.
-///
-/// An empty iterator results in `True`.
-///
-/// ## Examples
-///
-/// > empty() |> all(fn(n) { n % 2 == 0 })
-/// True
-///
-/// > from_list([2, 4, 6, 8]) |> all(fn(n) { n % 2 == 0 })
-/// True
-///
-/// > from_list([2, 4, 5, 8]) |> all(fn(n) { n % 2 == 0 })
-/// False
-///
-pub fn all(
- in iterator: Iterator(element),
- satisfying predicate: fn(element) -> Bool,
-) -> Bool {
- iterator.continuation
- |> do_all(predicate)
-}
+ /// Returns `True` if all elements emitted by the iterator satisfy the given predicate,
+ /// `False` otherwise.
+ ///
+ /// This function short-circuits once it finds a non-satisfying element.
+ ///
+ /// An empty iterator results in `True`.
+ ///
+ /// ## Examples
+ ///
+ /// > empty() |> all(fn(n) { n % 2 == 0 })
+ /// True
+ ///
+ /// > from_list([2, 4, 6, 8]) |> all(fn(n) { n % 2 == 0 })
+ /// True
+ ///
+ /// > from_list([2, 4, 5, 8]) |> all(fn(n) { n % 2 == 0 })
+ /// False
+ ///
+ pub fn all(
+ in iterator: Iterator(element),
+ satisfying predicate: fn(element) -> Bool,
+ ) -> Bool {
+ iterator.continuation
+ |> do_all(predicate)
+ }
-fn update_group_with(
- el: element,
-) -> fn(Result(List(element), Nil)) -> List(element) {
- fn(maybe_group) {
- case maybe_group {
- Ok(group) -> [el, ..group]
- Error(Nil) -> [el]
+ fn update_group_with(
+ el: element,
+ ) -> fn(Result(List(element), Nil)) -> List(element) {
+ fn(maybe_group) {
+ case maybe_group {
+ Ok(group) -> [el, ..group]
+ Error(Nil) -> [el]
+ }
}
}
-}
-fn group_updater(
- f: fn(element) -> key,
-) -> fn(element, Map(key, List(element))) -> Map(key, List(element)) {
- fn(elem, groups) {
- groups
- |> map.update(f(elem), update_group_with(elem))
+ fn group_updater(
+ f: fn(element) -> key,
+ ) -> fn(element, Map(key, List(element))) -> Map(key, List(element)) {
+ fn(elem, groups) {
+ groups
+ |> map.update(f(elem), update_group_with(elem))
+ }
}
-}
-/// Returns a `Map(k, List(element))` of elements from the given iterator
-/// grouped with the given key function.
-///
-/// The order within each group is preserved from the iterator.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3, 4, 5, 6]) |> group(by: fn(n) { n % 3 })
-/// map.from_list([#(0, [3, 6]), #(1, [1, 4]), #(2, [2, 5])])
-///
-pub fn group(
- in iterator: Iterator(element),
- by key: fn(element) -> key,
-) -> Map(key, List(element)) {
- iterator
- |> fold(map.new(), group_updater(key))
- |> map.map_values(fn(_, group) { list.reverse(group) })
-}
+ /// Returns a `Map(k, List(element))` of elements from the given iterator
+ /// grouped with the given key function.
+ ///
+ /// The order within each group is preserved from the iterator.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3, 4, 5, 6]) |> group(by: fn(n) { n % 3 })
+ /// map.from_list([#(0, [3, 6]), #(1, [1, 4]), #(2, [2, 5])])
+ ///
+ pub fn group(
+ in iterator: Iterator(element),
+ by key: fn(element) -> key,
+ ) -> Map(key, List(element)) {
+ iterator
+ |> fold(map.new(), group_updater(key))
+ |> map.map_values(fn(_, group) { list.reverse(group) })
+ }
-/// This function acts similar to fold, but does not take an initial state.
-/// Instead, it starts from the first yielded element
-/// and combines it with each subsequent element in turn using the given function.
-/// The function is called as f(current_element, accumulator).
-///
-/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator.
-///
-/// ## Examples
-///
-/// > from_list([]) |> reduce(fn(x, y) { x + y })
-/// Error(Nil)
-///
-/// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(x, y) { x + y })
-/// Ok(15)
-///
-pub fn reduce(
- over iterator: Iterator(e),
- with f: fn(e, e) -> e,
-) -> Result(e, Nil) {
- case iterator.continuation() {
- Stop -> Error(Nil)
- Continue(e, next) ->
- do_fold(next, f, e)
- |> Ok
+ /// This function acts similar to fold, but does not take an initial state.
+ /// Instead, it starts from the first yielded element
+ /// and combines it with each subsequent element in turn using the given function.
+ /// The function is called as f(current_element, accumulator).
+ ///
+ /// Returns `Ok` to indicate a successful run, and `Error` if called on an empty iterator.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([]) |> reduce(fn(x, y) { x + y })
+ /// Error(Nil)
+ ///
+ /// > from_list([1, 2, 3, 4, 5]) |> reduce(fn(x, y) { x + y })
+ /// Ok(15)
+ ///
+ pub fn reduce(
+ over iterator: Iterator(e),
+ with f: fn(e, e) -> e,
+ ) -> Result(e, Nil) {
+ case iterator.continuation() {
+ Stop -> Error(Nil)
+ Continue(e, next) ->
+ do_fold(next, f, e)
+ |> Ok
+ }
}
-}
-/// Returns the last element in the given iterator.
-///
-/// Returns `Error(Nil)` if the iterator is empty.
-///
-/// This function runs in linear time.
-///
-/// ## Examples
-///
-/// > empty() |> last
-/// Error(Nil)
-///
-/// > range(1, 10) |> last
-/// Ok(9)
-///
-pub fn last(iterator: Iterator(element)) -> Result(element, Nil) {
- iterator
- |> reduce(fn(elem, _) { elem })
-}
+ /// Returns the last element in the given iterator.
+ ///
+ /// Returns `Error(Nil)` if the iterator is empty.
+ ///
+ /// This function runs in linear time.
+ ///
+ /// ## Examples
+ ///
+ /// > empty() |> last
+ /// Error(Nil)
+ ///
+ /// > range(1, 10) |> last
+ /// Ok(9)
+ ///
+ pub fn last(iterator: Iterator(element)) -> Result(element, Nil) {
+ iterator
+ |> reduce(fn(elem, _) { elem })
+ }
-/// Creates an iterator that yields no elements.
-///
-/// ## Examples
-///
-/// > empty() |> to_list
-/// []
-///
-pub fn empty() -> Iterator(element) {
- Iterator(stop)
-}
+ /// Creates an iterator that yields no elements.
+ ///
+ /// ## Examples
+ ///
+ /// > empty() |> to_list
+ /// []
+ ///
+ pub fn empty() -> Iterator(element) {
+ Iterator(stop)
+ }
-/// Creates an iterator that yields exactly one element provided by calling the given function.
-///
-/// ## Examples
-///
-/// > once(fn() { 1 }) |> to_list
-/// [1]
-///
-pub fn once(f: fn() -> element) -> Iterator(element) {
- fn() { Continue(f(), stop) }
- |> Iterator
-}
+ /// Creates an iterator that yields exactly one element provided by calling the given function.
+ ///
+ /// ## Examples
+ ///
+ /// > once(fn() { 1 }) |> to_list
+ /// [1]
+ ///
+ pub fn once(f: fn() -> element) -> Iterator(element) {
+ fn() { Continue(f(), stop) }
+ |> Iterator
+ }
-/// Creates an iterator that yields the given element exactly once.
-///
-/// ## Examples
-///
-/// > single(1) |> to_list
-/// [1]
-///
-pub fn single(elem: element) -> Iterator(element) {
- once(fn() { elem })
-}
+ /// Creates an iterator that yields the given element exactly once.
+ ///
+ /// ## Examples
+ ///
+ /// > single(1) |> to_list
+ /// [1]
+ ///
+ pub fn single(elem: element) -> Iterator(element) {
+ once(fn() { elem })
+ }
-fn do_interleave(
- current: fn() -> Action(element),
- next: fn() -> Action(element),
-) -> Action(element) {
- case current() {
- Stop -> next()
- Continue(e, next_other) ->
- Continue(e, fn() { do_interleave(next, next_other) })
+ fn do_interleave(
+ current: fn() -> Action(element),
+ next: fn() -> Action(element),
+ ) -> Action(element) {
+ case current() {
+ Stop -> next()
+ Continue(e, next_other) ->
+ Continue(e, fn() { do_interleave(next, next_other) })
+ }
}
-}
-/// Creates an iterator that alternates between the two given iterators
-/// until both have run out.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3, 4]) |> interleave(from_list([11, 12, 13, 14])) |> to_list
-/// [1, 11, 2, 12, 3, 13, 4, 14]
-///
-/// > from_list([1, 2, 3, 4]) |> interleave(from_list([100])) |> to_list
-/// [1, 100, 2, 3, 4]
-///
-pub fn interleave(
- left: Iterator(element),
- with right: Iterator(element),
-) -> Iterator(element) {
- fn() { do_interleave(left.continuation, right.continuation) }
- |> Iterator
+ /// Creates an iterator that alternates between the two given iterators
+ /// until both have run out.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3, 4]) |> interleave(from_list([11, 12, 13, 14])) |> to_list
+ /// [1, 11, 2, 12, 3, 13, 4, 14]
+ ///
+ /// > from_list([1, 2, 3, 4]) |> interleave(from_list([100])) |> to_list
+ /// [1, 100, 2, 3, 4]
+ ///
+ pub fn interleave(
+ left: Iterator(element),
+ with right: Iterator(element),
+ ) -> Iterator(element) {
+ fn() { do_interleave(left.continuation, right.continuation) }
+ |> Iterator
+ }
}
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index 2a91733..33e32d1 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -18,1556 +18,1560 @@
//// }
////
-import gleam/int
-import gleam/pair
-import gleam/order.{Order}
-
-pub type List(elements) =
- List(elements)
-
-/// An error value returned by the `strict_zip` function.
-///
-pub type LengthMismatch {
- LengthMismatch
-}
+if erlang {
+ import gleam/int
+ import gleam/pair
+ import gleam/order.{Order}
+
+ pub type List(elements) =
+ List(elements)
+
+ /// An error value returned by the `strict_zip` function.
+ ///
+ pub type LengthMismatch {
+ LengthMismatch
+ }
-/// Counts the number of elements in a given list.
-///
-/// This function has to traverse the list to determine the number of elements,
-/// so it runs in linear time.
-///
-/// This function is natively implemented by the virtual machine and is highly
-/// optimised.
-///
-/// ## Examples
-///
-/// > length([])
-/// 0
-///
-/// > length([1])
-/// 1
-///
-/// > length([1, 2])
-/// 2
-///
-pub external fn length(of: List(a)) -> Int =
- "erlang" "length"
-
-/// Creates a new list from a given list containing the same elements but in the
-/// opposite order.
-///
-/// This function has to traverse the list to create the new reversed list, so
-/// it runs in linear time.
-///
-/// This function is natively implemented by the virtual machine and is highly
-/// optimised.
-///
-/// ## Examples
-///
-/// > reverse([])
-/// []
-///
-/// > reverse([1])
-/// [1]
-///
-/// > reverse([1, 2])
-/// [2, 1]
-///
-pub external fn reverse(List(a)) -> List(a) =
- "lists" "reverse"
-
-/// Determines whether or not the list is empty.
-///
-/// This function runs in constant time.
-///
-/// ## Examples
-///
-/// > is_empty([])
-/// True
-///
-/// > is_empty([1])
-/// False
-///
-/// > is_empty([1, 1])
-/// False
-///
-pub fn is_empty(list: List(a)) -> Bool {
- list == []
-}
+ /// Counts the number of elements in a given list.
+ ///
+ /// This function has to traverse the list to determine the number of elements,
+ /// so it runs in linear time.
+ ///
+ /// This function is natively implemented by the virtual machine and is highly
+ /// optimised.
+ ///
+ /// ## Examples
+ ///
+ /// > length([])
+ /// 0
+ ///
+ /// > length([1])
+ /// 1
+ ///
+ /// > length([1, 2])
+ /// 2
+ ///
+ pub external fn length(of: List(a)) -> Int =
+ "erlang" "length"
+
+ /// Creates a new list from a given list containing the same elements but in the
+ /// opposite order.
+ ///
+ /// This function has to traverse the list to create the new reversed list, so
+ /// it runs in linear time.
+ ///
+ /// This function is natively implemented by the virtual machine and is highly
+ /// optimised.
+ ///
+ /// ## Examples
+ ///
+ /// > reverse([])
+ /// []
+ ///
+ /// > reverse([1])
+ /// [1]
+ ///
+ /// > reverse([1, 2])
+ /// [2, 1]
+ ///
+ pub external fn reverse(List(a)) -> List(a) =
+ "lists" "reverse"
+
+ /// Determines whether or not the list is empty.
+ ///
+ /// This function runs in constant time.
+ ///
+ /// ## Examples
+ ///
+ /// > is_empty([])
+ /// True
+ ///
+ /// > is_empty([1])
+ /// False
+ ///
+ /// > is_empty([1, 1])
+ /// False
+ ///
+ pub fn is_empty(list: List(a)) -> Bool {
+ list == []
+ }
-/// Determines whether or not a given element exists within a given list.
-///
-/// This function traverses the list to find the element, so it runs in linear
-/// time.
-///
-/// ## Examples
-///
-/// > [] |> contains(any: 0)
-/// True
-///
-/// > [0] |> contains(any: 0)
-/// True
-///
-/// > [1] |> contains(any: 0)
-/// False
-///
-/// > [1, 1] |> contains(any: 0)
-/// False
-///
-/// > [1, 0] |> contains(any: 0)
-/// True
-///
-pub fn contains(list: List(a), any elem: a) -> Bool {
- case list {
- [] -> False
- [head, ..rest] -> head == elem || contains(rest, elem)
+ /// Determines whether or not a given element exists within a given list.
+ ///
+ /// This function traverses the list to find the element, so it runs in linear
+ /// time.
+ ///
+ /// ## Examples
+ ///
+ /// > [] |> contains(any: 0)
+ /// True
+ ///
+ /// > [0] |> contains(any: 0)
+ /// True
+ ///
+ /// > [1] |> contains(any: 0)
+ /// False
+ ///
+ /// > [1, 1] |> contains(any: 0)
+ /// False
+ ///
+ /// > [1, 0] |> contains(any: 0)
+ /// True
+ ///
+ pub fn contains(list: List(a), any elem: a) -> Bool {
+ case list {
+ [] -> False
+ [head, ..rest] -> head == elem || contains(rest, elem)
+ }
}
-}
-/// Gets the first element from the start of the list, if there is one.
-///
-/// ## Examples
-///
-/// > head([])
-/// Error(Nil)
-///
-/// > head([0])
-/// Ok(0)
-///
-/// > head([1, 2])
-/// Ok(1)
-///
-pub fn head(list: List(a)) -> Result(a, Nil) {
- case list {
- [] -> Error(Nil)
- [x, .._] -> Ok(x)
+ /// Gets the first element from the start of the list, if there is one.
+ ///
+ /// ## Examples
+ ///
+ /// > head([])
+ /// Error(Nil)
+ ///
+ /// > head([0])
+ /// Ok(0)
+ ///
+ /// > head([1, 2])
+ /// Ok(1)
+ ///
+ pub fn head(list: List(a)) -> Result(a, Nil) {
+ case list {
+ [] -> Error(Nil)
+ [x, .._] -> Ok(x)
+ }
}
-}
-/// Gets the list minus the first element. If the list is empty `Error(Nil)` is
-/// returned.
-///
-/// This function runs in constant time and does not make a copy of the list.
-///
-/// ## Examples
-///
-/// > tail([])
-/// Error(Nil)
-///
-/// > tail([0])
-/// Ok([])
-///
-/// > tail([1, 2])
-/// Ok([2])
-///
-pub fn tail(list: List(a)) -> Result(List(a), Nil) {
- case list {
- [] -> Error(Nil)
- [_, ..xs] -> Ok(xs)
+ /// Gets the list minus the first element. If the list is empty `Error(Nil)` is
+ /// returned.
+ ///
+ /// This function runs in constant time and does not make a copy of the list.
+ ///
+ /// ## Examples
+ ///
+ /// > tail([])
+ /// Error(Nil)
+ ///
+ /// > tail([0])
+ /// Ok([])
+ ///
+ /// > tail([1, 2])
+ /// Ok([2])
+ ///
+ pub fn tail(list: List(a)) -> Result(List(a), Nil) {
+ case list {
+ [] -> Error(Nil)
+ [_, ..xs] -> Ok(xs)
+ }
}
-}
-fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) {
- case list {
- [] -> reverse(acc)
- [x, ..xs] -> {
- let new_acc = case fun(x) {
- True -> [x, ..acc]
- False -> acc
+ fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..xs] -> {
+ let new_acc = case fun(x) {
+ True -> [x, ..acc]
+ False -> acc
+ }
+ do_filter(xs, fun, new_acc)
}
- do_filter(xs, fun, new_acc)
}
}
-}
-/// Returns a new list containing only the elements from the first list for
-/// which the given functions returns `True`.
-///
-/// ## Examples
-///
-/// > filter([2, 4, 6, 1], fn(x) { x > 2 })
-/// [4, 6]
-///
-/// > filter([2, 4, 6, 1], fn(x) { x > 6 })
-/// []
-///
-pub fn filter(list: List(a), for predicate: fn(a) -> Bool) -> List(a) {
- do_filter(list, predicate, [])
-}
+ /// Returns a new list containing only the elements from the first list for
+ /// which the given functions returns `True`.
+ ///
+ /// ## Examples
+ ///
+ /// > filter([2, 4, 6, 1], fn(x) { x > 2 })
+ /// [4, 6]
+ ///
+ /// > filter([2, 4, 6, 1], fn(x) { x > 6 })
+ /// []
+ ///
+ pub fn filter(list: List(a), for predicate: fn(a) -> Bool) -> List(a) {
+ do_filter(list, predicate, [])
+ }
-fn do_filter_map(
- list: List(a),
- fun: fn(a) -> Result(b, e),
- acc: List(b),
-) -> List(b) {
- case list {
- [] -> reverse(acc)
- [x, ..xs] -> {
- let new_acc = case fun(x) {
- Ok(x) -> [x, ..acc]
- Error(_) -> acc
+ fn do_filter_map(
+ list: List(a),
+ fun: fn(a) -> Result(b, e),
+ acc: List(b),
+ ) -> List(b) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..xs] -> {
+ let new_acc = case fun(x) {
+ Ok(x) -> [x, ..acc]
+ Error(_) -> acc
+ }
+ do_filter_map(xs, fun, new_acc)
}
- do_filter_map(xs, fun, new_acc)
}
}
-}
-
-/// Returns a new list containing only the elements from the first list for
-/// which the given functions returns `Ok(_)`.
-///
-/// ## Examples
-///
-/// > filter_map([2, 4, 6, 1], Error)
-/// []
-///
-/// > filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) })
-/// [3, 4, 6, 2]
-///
-pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) {
- do_filter_map(list, fun, [])
-}
-fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
- case list {
- [] -> reverse(acc)
- [x, ..xs] -> do_map(xs, fun, [fun(x), ..acc])
+ /// Returns a new list containing only the elements from the first list for
+ /// which the given functions returns `Ok(_)`.
+ ///
+ /// ## Examples
+ ///
+ /// > filter_map([2, 4, 6, 1], Error)
+ /// []
+ ///
+ /// > filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) })
+ /// [3, 4, 6, 2]
+ ///
+ pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) {
+ do_filter_map(list, fun, [])
}
-}
-/// Returns a new list containing only the elements of the first list after the
-/// function has been applied to each one.
-///
-/// ## Examples
-///
-/// > map([2, 4, 6], fn(x) { x * 2 })
-/// [4, 8, 12]
-///
-pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) {
- do_map(list, fun, [])
-}
+ fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..xs] -> do_map(xs, fun, [fun(x), ..acc])
+ }
+ }
-/// Similar to map but also lets you pass around an accumulated value.
-///
-/// ## Examples
-///
-/// ```
-/// > map_fold(
-/// over: [1, 2, 3],
-/// from: 100,
-/// with: fn(i, memo) { #(i * 2, memo + i) }
-/// )
-/// #([2, 4, 6], 106)
-/// ```
-///
-pub fn map_fold(
- over list: List(a),
- from memo: memo,
- with fun: fn(a, memo) -> #(b, memo),
-) -> #(List(b), memo) {
- fold(
- over: list,
- from: #([], memo),
- with: fn(item, acc) {
- let #(items, current_memo) = acc
- let #(next_item, next_memo) = fun(item, current_memo)
- #([next_item, ..items], next_memo)
- },
- )
- |> pair.map_first(reverse)
-}
+ /// Returns a new list containing only the elements of the first list after the
+ /// function has been applied to each one.
+ ///
+ /// ## Examples
+ ///
+ /// > map([2, 4, 6], fn(x) { x * 2 })
+ /// [4, 8, 12]
+ ///
+ pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) {
+ do_map(list, fun, [])
+ }
-fn do_index_map(
- list: List(a),
- fun: fn(Int, a) -> b,
- index: Int,
- acc: List(b),
-) -> List(b) {
- case list {
- [] -> reverse(acc)
- [x, ..xs] -> do_index_map(xs, fun, index + 1, [fun(index, x), ..acc])
+ /// Similar to map but also lets you pass around an accumulated value.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > map_fold(
+ /// over: [1, 2, 3],
+ /// from: 100,
+ /// with: fn(i, memo) { #(i * 2, memo + i) }
+ /// )
+ /// #([2, 4, 6], 106)
+ /// ```
+ ///
+ pub fn map_fold(
+ over list: List(a),
+ from memo: memo,
+ with fun: fn(a, memo) -> #(b, memo),
+ ) -> #(List(b), memo) {
+ fold(
+ over: list,
+ from: #([], memo),
+ with: fn(item, acc) {
+ let #(items, current_memo) = acc
+ let #(next_item, next_memo) = fun(item, current_memo)
+ #([next_item, ..items], next_memo)
+ },
+ )
+ |> pair.map_first(reverse)
}
-}
-/// Returns a new list containing only the elements of the first list after the
-/// function has been applied to each one and their index.
-///
-/// The index starts at 0, so the first element is 0, the second is 1, and so
-/// on.
-///
-/// ## Examples
-///
-/// > index_map(["a", "b"], fn(i, x) { #(i, x) })
-/// [#(0, "a"), #(1, "b")]
-///
-pub fn index_map(list: List(a), with fun: fn(Int, a) -> b) -> List(b) {
- do_index_map(list, fun, 0, [])
-}
+ fn do_index_map(
+ list: List(a),
+ fun: fn(Int, a) -> b,
+ index: Int,
+ acc: List(b),
+ ) -> List(b) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..xs] -> do_index_map(xs, fun, index + 1, [fun(index, x), ..acc])
+ }
+ }
-fn do_try_map(
- list: List(a),
- fun: fn(a) -> Result(b, e),
- acc: List(b),
-) -> Result(List(b), e) {
- case list {
- [] -> Ok(reverse(acc))
- [x, ..xs] ->
- case fun(x) {
- Ok(y) -> do_try_map(xs, fun, [y, ..acc])
- Error(error) -> Error(error)
- }
+ /// Returns a new list containing only the elements of the first list after the
+ /// function has been applied to each one and their index.
+ ///
+ /// The index starts at 0, so the first element is 0, the second is 1, and so
+ /// on.
+ ///
+ /// ## Examples
+ ///
+ /// > index_map(["a", "b"], fn(i, x) { #(i, x) })
+ /// [#(0, "a"), #(1, "b")]
+ ///
+ pub fn index_map(list: List(a), with fun: fn(Int, a) -> b) -> List(b) {
+ do_index_map(list, fun, 0, [])
}
-}
-/// Takes a function that returns a Result applies it to each element in a
-/// given list in tern.
-///
-/// If the function returns `Ok(new_value)` for all elements in the list then a
-/// list of the new values is returned.
-///
-/// If the function returns `Error(reason)` for any of the elements then it is
-/// returned immediately. None of the elements in the list are processed after
-/// one returns an `Error`.
-///
-/// ## Examples
-///
-/// > try_map([1, 2, 3], fn(x) { Ok(x + 2) })
-/// Ok([3, 4, 5])
-///
-/// > try_map([1, 2, 3], fn(x) { Error(0) })
-/// Error(0)
-///
-/// > try_map([[1], [2, 3]], head)
-/// Ok([1, 2])
-///
-/// > try_map([[1], [], [2]], head)
-/// Error(Nil)
-///
-pub fn try_map(
- over list: List(a),
- with fun: fn(a) -> Result(b, e),
-) -> Result(List(b), e) {
- do_try_map(list, fun, [])
-}
+ fn do_try_map(
+ list: List(a),
+ fun: fn(a) -> Result(b, e),
+ acc: List(b),
+ ) -> Result(List(b), e) {
+ case list {
+ [] -> Ok(reverse(acc))
+ [x, ..xs] ->
+ case fun(x) {
+ Ok(y) -> do_try_map(xs, fun, [y, ..acc])
+ Error(error) -> Error(error)
+ }
+ }
+ }
-/// Returns a list that is the given list with up to the given number of
-/// elements removed from the front of the list.
-///
-/// If the element has less than the number of elements an empty list is
-/// returned.
-///
-/// This function runs in linear time but does not copy the list.
-///
-/// ## Examples
-///
-/// > drop([1, 2, 3, 4], 2)
-/// [3, 4]
-///
-/// > drop([1, 2, 3, 4], 9)
-/// []
-///
-pub fn drop(from list: List(a), up_to n: Int) -> List(a) {
- case n <= 0 {
- True -> list
- False ->
- case list {
- [] -> []
- [_, ..xs] -> drop(xs, n - 1)
- }
+ /// Takes a function that returns a Result applies it to each element in a
+ /// given list in tern.
+ ///
+ /// If the function returns `Ok(new_value)` for all elements in the list then a
+ /// list of the new values is returned.
+ ///
+ /// If the function returns `Error(reason)` for any of the elements then it is
+ /// returned immediately. None of the elements in the list are processed after
+ /// one returns an `Error`.
+ ///
+ /// ## Examples
+ ///
+ /// > try_map([1, 2, 3], fn(x) { Ok(x + 2) })
+ /// Ok([3, 4, 5])
+ ///
+ /// > try_map([1, 2, 3], fn(x) { Error(0) })
+ /// Error(0)
+ ///
+ /// > try_map([[1], [2, 3]], head)
+ /// Ok([1, 2])
+ ///
+ /// > try_map([[1], [], [2]], head)
+ /// Error(Nil)
+ ///
+ pub fn try_map(
+ over list: List(a),
+ with fun: fn(a) -> Result(b, e),
+ ) -> Result(List(b), e) {
+ do_try_map(list, fun, [])
}
-}
-fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) {
- case n <= 0 {
- True -> reverse(acc)
- False ->
- case list {
- [] -> reverse(acc)
- [x, ..xs] -> do_take(xs, n - 1, [x, ..acc])
- }
+ /// Returns a list that is the given list with up to the given number of
+ /// elements removed from the front of the list.
+ ///
+ /// If the element has less than the number of elements an empty list is
+ /// returned.
+ ///
+ /// This function runs in linear time but does not copy the list.
+ ///
+ /// ## Examples
+ ///
+ /// > drop([1, 2, 3, 4], 2)
+ /// [3, 4]
+ ///
+ /// > drop([1, 2, 3, 4], 9)
+ /// []
+ ///
+ pub fn drop(from list: List(a), up_to n: Int) -> List(a) {
+ case n <= 0 {
+ True -> list
+ False ->
+ case list {
+ [] -> []
+ [_, ..xs] -> drop(xs, n - 1)
+ }
+ }
}
-}
-/// Returns a list containing the first given number of elements from the given
-/// list.
-///
-/// If the element has less than the number of elements then the full list is
-/// returned.
-///
-/// This function runs in linear time but does not copy the list.
-///
-/// ## Examples
-///
-/// > take([1, 2, 3, 4], 2)
-/// [1, 2]
-///
-/// > take([1, 2, 3, 4], 9)
-/// [1, 2, 3, 4]
-///
-pub fn take(from list: List(a), up_to n: Int) -> List(a) {
- do_take(list, n, [])
-}
+ fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) {
+ case n <= 0 {
+ True -> reverse(acc)
+ False ->
+ case list {
+ [] -> reverse(acc)
+ [x, ..xs] -> do_take(xs, n - 1, [x, ..acc])
+ }
+ }
+ }
-/// Returns a new empty list.
-///
-/// ## Examples
-///
-/// > new()
-/// []
-///
-pub fn new() -> List(a) {
- []
-}
+ /// Returns a list containing the first given number of elements from the given
+ /// list.
+ ///
+ /// If the element has less than the number of elements then the full list is
+ /// returned.
+ ///
+ /// This function runs in linear time but does not copy the list.
+ ///
+ /// ## Examples
+ ///
+ /// > take([1, 2, 3, 4], 2)
+ /// [1, 2]
+ ///
+ /// > take([1, 2, 3, 4], 9)
+ /// [1, 2, 3, 4]
+ ///
+ pub fn take(from list: List(a), up_to n: Int) -> List(a) {
+ do_take(list, n, [])
+ }
-/// Joins one list onto the end of another.
-///
-/// This function runs in linear time, and it traverses and copies the first
-/// list.
-///
-/// ## Examples
-///
-/// > append([1, 2], [3])
-/// [1, 2, 3]
-///
-pub external fn append(List(a), List(a)) -> List(a) =
- "lists" "append"
-
-fn do_flatten(lists: List(List(a)), acc: List(a)) -> List(a) {
- case lists {
- [] -> acc
- [l, ..rest] -> do_flatten(rest, append(acc, l))
+ /// Returns a new empty list.
+ ///
+ /// ## Examples
+ ///
+ /// > new()
+ /// []
+ ///
+ pub fn new() -> List(a) {
+ []
}
-}
-/// Flattens a list of lists into a single list.
-///
-/// This function runs in linear time, and it traverses and copies all the
-/// inner lists.
-///
-/// ## Examples
-///
-/// > flatten([[1], [2, 3], []])
-/// [1, 2, 3]
-///
-pub fn flatten(lists: List(List(a))) -> List(a) {
- do_flatten(lists, [])
-}
+ /// Joins one list onto the end of another.
+ ///
+ /// This function runs in linear time, and it traverses and copies the first
+ /// list.
+ ///
+ /// ## Examples
+ ///
+ /// > append([1, 2], [3])
+ /// [1, 2, 3]
+ ///
+ pub external fn append(List(a), List(a)) -> List(a) =
+ "lists" "append"
+
+ fn do_flatten(lists: List(List(a)), acc: List(a)) -> List(a) {
+ case lists {
+ [] -> acc
+ [l, ..rest] -> do_flatten(rest, append(acc, l))
+ }
+ }
-/// Map and flatten the result
-///
-/// ## Examples
-///
-/// ```
-/// > flat_map([2, 4, 6], fn(x) { [x, x + 1] })
-/// [2, 3, 4, 5, 6, 7]
-/// ```
-///
-pub fn flat_map(over list: List(a), with fun: fn(a) -> List(b)) -> List(b) {
- map(list, fun)
- |> flatten
-}
+ /// Flattens a list of lists into a single list.
+ ///
+ /// This function runs in linear time, and it traverses and copies all the
+ /// inner lists.
+ ///
+ /// ## Examples
+ ///
+ /// > flatten([[1], [2, 3], []])
+ /// [1, 2, 3]
+ ///
+ pub fn flatten(lists: List(List(a))) -> List(a) {
+ do_flatten(lists, [])
+ }
-/// Reduces a list of elements into a single value by calling a given function
-/// on each element, going from left to right.
-///
-/// `fold([1, 2, 3], 0, add)` is the equivalent of `add(3, add(2, add(1, 0)))`.
-///
-/// This function runs in linear time.
-///
-pub fn fold(over list: List(a), from initial: b, with fun: fn(a, b) -> b) -> b {
- case list {
- [] -> initial
- [x, ..rest] -> fold(rest, fun(x, initial), fun)
+ /// Map and flatten the result
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > flat_map([2, 4, 6], fn(x) { [x, x + 1] })
+ /// [2, 3, 4, 5, 6, 7]
+ /// ```
+ ///
+ pub fn flat_map(over list: List(a), with fun: fn(a) -> List(b)) -> List(b) {
+ map(list, fun)
+ |> flatten
}
-}
-/// Reduces a list of elements into a single value by calling a given function
-/// on each element, going from right to left.
-///
-/// `fold_right([1, 2, 3], 0, add)` is the equivalent of
-/// `add(1, add(2, add(3, 0)))`.
-///
-/// This function runs in linear time.
-///
-/// Unlike `fold` this function is not tail recursive. Where possible use
-/// `fold` instead as it will use less memory.
-///
-pub fn fold_right(
- over list: List(a),
- from initial: b,
- with fun: fn(a, b) -> b,
-) -> b {
- case list {
- [] -> initial
- [x, ..rest] -> fun(x, fold_right(rest, initial, fun))
+ /// Reduces a list of elements into a single value by calling a given function
+ /// on each element, going from left to right.
+ ///
+ /// `fold([1, 2, 3], 0, add)` is the equivalent of `add(3, add(2, add(1, 0)))`.
+ ///
+ /// This function runs in linear time.
+ ///
+ pub fn fold(over list: List(a), from initial: b, with fun: fn(a, b) -> b) -> b {
+ case list {
+ [] -> initial
+ [x, ..rest] -> fold(rest, fun(x, initial), fun)
+ }
}
-}
-fn do_index_fold(
- over: List(a),
- acc: b,
- with: fn(Int, a, b) -> b,
- index: Int,
-) -> b {
- case over {
- [] -> acc
- [first, ..rest] ->
- do_index_fold(rest, with(index, first, acc), with, index + 1)
+ /// Reduces a list of elements into a single value by calling a given function
+ /// on each element, going from right to left.
+ ///
+ /// `fold_right([1, 2, 3], 0, add)` is the equivalent of
+ /// `add(1, add(2, add(3, 0)))`.
+ ///
+ /// This function runs in linear time.
+ ///
+ /// Unlike `fold` this function is not tail recursive. Where possible use
+ /// `fold` instead as it will use less memory.
+ ///
+ pub fn fold_right(
+ over list: List(a),
+ from initial: b,
+ with fun: fn(a, b) -> b,
+ ) -> b {
+ case list {
+ [] -> initial
+ [x, ..rest] -> fun(x, fold_right(rest, initial, fun))
+ }
}
-}
-/// Like fold but the folding function also receives the index of the current element.
-///
-/// ## Examples
-///
-/// ```
-/// ["a", "b", "c"]
-/// |> list.index_fold([], fn(index, item, acc) { ... })
-/// ```
-///
-pub fn index_fold(
- over over: List(a),
- from initial: b,
- with fun: fn(Int, a, b) -> b,
-) -> b {
- do_index_fold(over, initial, fun, 0)
-}
+ fn do_index_fold(
+ over: List(a),
+ acc: b,
+ with: fn(Int, a, b) -> b,
+ index: Int,
+ ) -> b {
+ case over {
+ [] -> acc
+ [first, ..rest] ->
+ do_index_fold(rest, with(index, first, acc), with, index + 1)
+ }
+ }
-/// A variant of fold that might fail.
-///
-/// The folding function should return `Result(accumulator, error)
-/// If the returned value is `Ok(accumulator)` try_fold will try the next value in the list.
-/// If the returned value is `Error(error)` try_fold will stop and return that error.
-///
-/// ## Examples
-///
-/// ```
-/// [1, 2, 3, 4]
-/// |> try_fold(0, fn(i, acc) {
-/// case i < 3 {
-/// True -> Ok(acc + i)
-/// False -> Error(Nil)
-/// }
-/// })
-/// ```
-///
-pub fn try_fold(
- over collection: List(a),
- from accumulator: b,
- with fun: fn(a, b) -> Result(b, e),
-) -> Result(b, e) {
- case collection {
- [] -> Ok(accumulator)
- [first, ..rest] ->
- case fun(first, accumulator) {
- Ok(next_accumulator) -> try_fold(rest, next_accumulator, fun)
- Error(err) -> Error(err)
- }
+ /// Like fold but the folding function also receives the index of the current element.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// ["a", "b", "c"]
+ /// |> list.index_fold([], fn(index, item, acc) { ... })
+ /// ```
+ ///
+ pub fn index_fold(
+ over over: List(a),
+ from initial: b,
+ with fun: fn(Int, a, b) -> b,
+ ) -> b {
+ do_index_fold(over, initial, fun, 0)
}
-}
-pub type ContinueOrStop(a) {
- Continue(a)
- Stop(a)
-}
+ /// A variant of fold that might fail.
+ ///
+ /// The folding function should return `Result(accumulator, error)
+ /// If the returned value is `Ok(accumulator)` try_fold will try the next value in the list.
+ /// If the returned value is `Error(error)` try_fold will stop and return that error.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// [1, 2, 3, 4]
+ /// |> try_fold(0, fn(i, acc) {
+ /// case i < 3 {
+ /// True -> Ok(acc + i)
+ /// False -> Error(Nil)
+ /// }
+ /// })
+ /// ```
+ ///
+ pub fn try_fold(
+ over collection: List(a),
+ from accumulator: b,
+ with fun: fn(a, b) -> Result(b, e),
+ ) -> Result(b, e) {
+ case collection {
+ [] -> Ok(accumulator)
+ [first, ..rest] ->
+ case fun(first, accumulator) {
+ Ok(next_accumulator) -> try_fold(rest, next_accumulator, fun)
+ Error(err) -> Error(err)
+ }
+ }
+ }
-/// A variant of fold that allows to stop folding earlier.
-///
-/// The folding function should return `ContinueOrStop(accumulator)
-/// If the returned value is `Continue(accumulator)` fold_until will try the next value in the list.
-/// If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator.
-///
-/// ## Examples
-///
-/// ```
-/// [1, 2, 3, 4]
-/// |> fold_until(0, fn(i, acc) {
-/// case i < 3 {
-/// True -> Continue(acc + i)
-/// False -> Stop(acc)
-/// }
-/// })
-/// ```
-///
-pub fn fold_until(
- over collection: List(a),
- from accumulator: b,
- with fun: fn(a, b) -> ContinueOrStop(b),
-) -> b {
- case collection {
- [] -> accumulator
- [first, ..rest] ->
- case fun(first, accumulator) {
- Continue(next_accumulator) -> fold_until(rest, next_accumulator, fun)
- Stop(b) -> b
- }
+ pub type ContinueOrStop(a) {
+ Continue(a)
+ Stop(a)
}
-}
-/// Finds the first element in a given list for which the given function returns
-/// True.
-///
-/// Returns `Error(Nil)` if no the function does not return True for any of the
-/// elements.
-///
-/// ## Examples
-///
-/// > find([1, 2, 3], fn(x) { x > 2 })
-/// Ok(3)
-///
-/// > find([1, 2, 3], fn(x) { x > 4 })
-/// Error(Nil)
-///
-/// > find([], fn(x) { True })
-/// Error(Nil)
-///
-pub fn find(
- in haystack: List(a),
- one_that is_desired: fn(a) -> Bool,
-) -> Result(a, Nil) {
- case haystack {
- [] -> Error(Nil)
- [x, ..rest] ->
- case is_desired(x) {
- True -> Ok(x)
- _ -> find(in: rest, one_that: is_desired)
- }
+ /// A variant of fold that allows to stop folding earlier.
+ ///
+ /// The folding function should return `ContinueOrStop(accumulator)
+ /// If the returned value is `Continue(accumulator)` fold_until will try the next value in the list.
+ /// If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// [1, 2, 3, 4]
+ /// |> fold_until(0, fn(i, acc) {
+ /// case i < 3 {
+ /// True -> Continue(acc + i)
+ /// False -> Stop(acc)
+ /// }
+ /// })
+ /// ```
+ ///
+ pub fn fold_until(
+ over collection: List(a),
+ from accumulator: b,
+ with fun: fn(a, b) -> ContinueOrStop(b),
+ ) -> b {
+ case collection {
+ [] -> accumulator
+ [first, ..rest] ->
+ case fun(first, accumulator) {
+ Continue(next_accumulator) -> fold_until(rest, next_accumulator, fun)
+ Stop(b) -> b
+ }
+ }
}
-}
-/// Finds the first element in a given list for which the given function returns
-/// `Ok(new_value)` and return the new value for that element.
-///
-/// Returns `Error(Nil)` if no the function does not return Ok for any of the
-/// elements.
-///
-/// ## Examples
-///
-/// > find_map([[], [2], [3]], head)
-/// Ok(2)
-///
-/// > find_map([[], []], head)
-/// Error(Nil)
-///
-/// > find_map([], head)
-/// Error(Nil)
-///
-pub fn find_map(
- in haystack: List(a),
- with fun: fn(a) -> Result(b, c),
-) -> Result(b, Nil) {
- case haystack {
- [] -> Error(Nil)
- [x, ..rest] ->
- case fun(x) {
- Ok(x) -> Ok(x)
- _ -> find_map(in: rest, with: fun)
- }
+ /// Finds the first element in a given list for which the given function returns
+ /// True.
+ ///
+ /// Returns `Error(Nil)` if no the function does not return True for any of the
+ /// elements.
+ ///
+ /// ## Examples
+ ///
+ /// > find([1, 2, 3], fn(x) { x > 2 })
+ /// Ok(3)
+ ///
+ /// > find([1, 2, 3], fn(x) { x > 4 })
+ /// Error(Nil)
+ ///
+ /// > find([], fn(x) { True })
+ /// Error(Nil)
+ ///
+ pub fn find(
+ in haystack: List(a),
+ one_that is_desired: fn(a) -> Bool,
+ ) -> Result(a, Nil) {
+ case haystack {
+ [] -> Error(Nil)
+ [x, ..rest] ->
+ case is_desired(x) {
+ True -> Ok(x)
+ _ -> find(in: rest, one_that: is_desired)
+ }
+ }
}
-}
-/// Returns True if the given function returns True for all the elements in
-/// the given list. If the function returns False for any of the elements it
-/// immediately returns False without checking the rest of the list.
-///
-/// ## Examples
-///
-/// > all([], fn(x) { x > 3 })
-/// True
-///
-/// > all([4, 5], fn(x) { x > 3 })
-/// True
-///
-/// > all([4, 3], fn(x) { x > 3 })
-/// False
-///
-pub fn all(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
- case list {
- [] -> True
- [x, ..rest] -> predicate(x) && all(rest, predicate)
+ /// Finds the first element in a given list for which the given function returns
+ /// `Ok(new_value)` and return the new value for that element.
+ ///
+ /// Returns `Error(Nil)` if no the function does not return Ok for any of the
+ /// elements.
+ ///
+ /// ## Examples
+ ///
+ /// > find_map([[], [2], [3]], head)
+ /// Ok(2)
+ ///
+ /// > find_map([[], []], head)
+ /// Error(Nil)
+ ///
+ /// > find_map([], head)
+ /// Error(Nil)
+ ///
+ pub fn find_map(
+ in haystack: List(a),
+ with fun: fn(a) -> Result(b, c),
+ ) -> Result(b, Nil) {
+ case haystack {
+ [] -> Error(Nil)
+ [x, ..rest] ->
+ case fun(x) {
+ Ok(x) -> Ok(x)
+ _ -> find_map(in: rest, with: fun)
+ }
+ }
}
-}
-/// Returns True if the given function returns True for any the elements in
-/// the given list. If the function returns True for any of the elements it
-/// immediately returns True without checking the rest of the list.
-///
-/// ## Examples
-///
-/// > any([], fn(x) { x > 3 })
-/// False
-///
-/// > any([4, 5], fn(x) { x > 3 })
-/// False
-///
-/// > any([4, 3], fn(x) { x > 3 })
-/// True
-///
-/// > any([3, 4], fn(x) { x > 3 })
-/// True
-///
-pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
- case list {
- [] -> False
- [x, ..rest] -> predicate(x) || any(rest, predicate)
+ /// Returns True if the given function returns True for all the elements in
+ /// the given list. If the function returns False for any of the elements it
+ /// immediately returns False without checking the rest of the list.
+ ///
+ /// ## Examples
+ ///
+ /// > all([], fn(x) { x > 3 })
+ /// True
+ ///
+ /// > all([4, 5], fn(x) { x > 3 })
+ /// True
+ ///
+ /// > all([4, 3], fn(x) { x > 3 })
+ /// False
+ ///
+ pub fn all(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
+ case list {
+ [] -> True
+ [x, ..rest] -> predicate(x) && all(rest, predicate)
+ }
}
-}
-fn do_zip(xs: List(a), ys: List(b), acc: List(#(a, b))) -> List(#(a, b)) {
- case xs, ys {
- [x, ..xs], [y, ..ys] -> do_zip(xs, ys, [#(x, y), ..acc])
- _, _ -> reverse(acc)
+ /// Returns True if the given function returns True for any the elements in
+ /// the given list. If the function returns True for any of the elements it
+ /// immediately returns True without checking the rest of the list.
+ ///
+ /// ## Examples
+ ///
+ /// > any([], fn(x) { x > 3 })
+ /// False
+ ///
+ /// > any([4, 5], fn(x) { x > 3 })
+ /// False
+ ///
+ /// > any([4, 3], fn(x) { x > 3 })
+ /// True
+ ///
+ /// > any([3, 4], fn(x) { x > 3 })
+ /// True
+ ///
+ pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
+ case list {
+ [] -> False
+ [x, ..rest] -> predicate(x) || any(rest, predicate)
+ }
}
-}
-/// Takes two lists and returns a single list of 2 item tuples.
-///
-/// If one of the lists is longer than the other the remaining elements from
-/// the longer list are not used.
-///
-/// ## Examples
-///
-/// > zip([], [])
-/// []
-///
-/// > zip([1, 2], [3])
-/// [#(1, 3)]
-///
-/// > zip([1], [3, 4])
-/// [#(1, 3)]
-///
-/// > zip([1, 2], [3, 4])
-/// [#(1, 3), #(2, 4)]
-///
-pub fn zip(xs: List(a), ys: List(b)) -> List(#(a, b)) {
- do_zip(xs, ys, [])
-}
+ fn do_zip(xs: List(a), ys: List(b), acc: List(#(a, b))) -> List(#(a, b)) {
+ case xs, ys {
+ [x, ..xs], [y, ..ys] -> do_zip(xs, ys, [#(x, y), ..acc])
+ _, _ -> reverse(acc)
+ }
+ }
-/// Takes two lists and returns a single list of 2 item tuples.
-///
-/// If one of the lists is longer than the other an Error is returned.
-///
-/// ## Examples
-///
-/// > strict_zip([], [])
-/// Ok([])
-///
-/// > strict_zip([1, 2], [3])
-/// Error(LengthMismatch)
-///
-/// > strict_zip([1], [3, 4])
-/// Error(LengthMismatch)
-///
-/// > strict_zip([1, 2], [3, 4])
-/// Ok([#(1, 3), #(2, 4)])
-///
-pub fn strict_zip(
- l1: List(a),
- l2: List(b),
-) -> Result(List(#(a, b)), LengthMismatch) {
- case length(of: l1) == length(of: l2) {
- True -> Ok(zip(l1, l2))
- False -> Error(LengthMismatch)
+ /// Takes two lists and returns a single list of 2 item tuples.
+ ///
+ /// If one of the lists is longer than the other the remaining elements from
+ /// the longer list are not used.
+ ///
+ /// ## Examples
+ ///
+ /// > zip([], [])
+ /// []
+ ///
+ /// > zip([1, 2], [3])
+ /// [#(1, 3)]
+ ///
+ /// > zip([1], [3, 4])
+ /// [#(1, 3)]
+ ///
+ /// > zip([1, 2], [3, 4])
+ /// [#(1, 3), #(2, 4)]
+ ///
+ pub fn zip(xs: List(a), ys: List(b)) -> List(#(a, b)) {
+ do_zip(xs, ys, [])
}
-}
-fn do_unzip(input, xs, ys) {
- case input {
- [] -> #(reverse(xs), reverse(ys))
- [#(x, y), ..rest] -> do_unzip(rest, [x, ..xs], [y, ..ys])
+ /// Takes two lists and returns a single list of 2 item tuples.
+ ///
+ /// If one of the lists is longer than the other an Error is returned.
+ ///
+ /// ## Examples
+ ///
+ /// > strict_zip([], [])
+ /// Ok([])
+ ///
+ /// > strict_zip([1, 2], [3])
+ /// Error(LengthMismatch)
+ ///
+ /// > strict_zip([1], [3, 4])
+ /// Error(LengthMismatch)
+ ///
+ /// > strict_zip([1, 2], [3, 4])
+ /// Ok([#(1, 3), #(2, 4)])
+ ///
+ pub fn strict_zip(
+ l1: List(a),
+ l2: List(b),
+ ) -> Result(List(#(a, b)), LengthMismatch) {
+ case length(of: l1) == length(of: l2) {
+ True -> Ok(zip(l1, l2))
+ False -> Error(LengthMismatch)
+ }
}
-}
-/// Takes a single list of 2 item tuples and returns two lists.
-///
-/// ## Examples
-///
-/// > unzip([#(1, 2), #(3, 4)])
-/// #([1, 3], [2, 4])
-///
-/// > unzip([])
-/// #([], [])
-///
-pub fn unzip(input: List(#(a, b))) -> #(List(a), List(b)) {
- do_unzip(input, [], [])
-}
+ fn do_unzip(input, xs, ys) {
+ case input {
+ [] -> #(reverse(xs), reverse(ys))
+ [#(x, y), ..rest] -> do_unzip(rest, [x, ..xs], [y, ..ys])
+ }
+ }
-fn do_intersperse(list: List(a), separator: a, acc: List(a)) -> List(a) {
- case list {
- [] -> reverse(acc)
- [x, ..rest] -> do_intersperse(rest, separator, [x, separator, ..acc])
+ /// Takes a single list of 2 item tuples and returns two lists.
+ ///
+ /// ## Examples
+ ///
+ /// > unzip([#(1, 2), #(3, 4)])
+ /// #([1, 3], [2, 4])
+ ///
+ /// > unzip([])
+ /// #([], [])
+ ///
+ pub fn unzip(input: List(#(a, b))) -> #(List(a), List(b)) {
+ do_unzip(input, [], [])
}
-}
-/// Inserts a given value between each existing element in a given list.
-///
-/// This function runs in linear time and copies the list.
-///
-/// ## Examples
-///
-/// > intersperse([1, 1, 1], 2)
-/// [1, 2, 1, 2, 1]
-///
-/// > intersperse([], 2)
-/// []
-///
-pub fn intersperse(list: List(a), with elem: a) -> List(a) {
- case list {
- [] | [_] -> list
- [x, ..rest] -> do_intersperse(rest, elem, [x])
+ fn do_intersperse(list: List(a), separator: a, acc: List(a)) -> List(a) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..rest] -> do_intersperse(rest, separator, [x, separator, ..acc])
+ }
}
-}
-/// Returns the element in the Nth position in the list, with 0 being the first
-/// position.
-///
-/// Error(Nil) is returned if the list is not long enough for the given index.
-///
-/// ## Examples
-///
-/// > at([1, 2, 3], 1)
-/// Ok(2)
-///
-/// > at([1, 2, 3], 5)
-/// Error(Nil)
-///
-pub fn at(in list: List(a), get index: Int) -> Result(a, Nil) {
- case index < 0 {
- True -> Error(Nil)
- False ->
- case list {
- [] -> Error(Nil)
- [x, ..rest] ->
- case index == 0 {
- True -> Ok(x)
- False -> at(rest, index - 1)
- }
- }
+ /// Inserts a given value between each existing element in a given list.
+ ///
+ /// This function runs in linear time and copies the list.
+ ///
+ /// ## Examples
+ ///
+ /// > intersperse([1, 1, 1], 2)
+ /// [1, 2, 1, 2, 1]
+ ///
+ /// > intersperse([], 2)
+ /// []
+ ///
+ pub fn intersperse(list: List(a), with elem: a) -> List(a) {
+ case list {
+ [] | [_] -> list
+ [x, ..rest] -> do_intersperse(rest, elem, [x])
+ }
}
-}
-/// Removes any duplicate elements from a given list.
-///
-/// This function returns in log-linear time (n log n).
-///
-/// ## Examples
-///
-/// > unique([1, 1, 1, 4, 7, 3, 3, 4])
-/// [1, 4, 7, 3]
-///
-pub fn unique(list: List(a)) -> List(a) {
- case list {
- [] -> []
- [x, ..rest] -> [x, ..unique(filter(rest, fn(y) { y != x }))]
+ /// Returns the element in the Nth position in the list, with 0 being the first
+ /// position.
+ ///
+ /// Error(Nil) is returned if the list is not long enough for the given index.
+ ///
+ /// ## Examples
+ ///
+ /// > at([1, 2, 3], 1)
+ /// Ok(2)
+ ///
+ /// > at([1, 2, 3], 5)
+ /// Error(Nil)
+ ///
+ pub fn at(in list: List(a), get index: Int) -> Result(a, Nil) {
+ case index < 0 {
+ True -> Error(Nil)
+ False ->
+ case list {
+ [] -> Error(Nil)
+ [x, ..rest] ->
+ case index == 0 {
+ True -> Ok(x)
+ False -> at(rest, index - 1)
+ }
+ }
+ }
}
-}
-fn merge_sort(a: List(a), b: List(a), compare: fn(a, a) -> Order) -> List(a) {
- case a, b {
- [], _ -> b
- _, [] -> a
- [ax, ..ar], [bx, ..br] ->
- case compare(ax, bx) {
- order.Lt -> [ax, ..merge_sort(ar, b, compare)]
- _ -> [bx, ..merge_sort(a, br, compare)]
- }
+ /// Removes any duplicate elements from a given list.
+ ///
+ /// This function returns in log-linear time (n log n).
+ ///
+ /// ## Examples
+ ///
+ /// > unique([1, 1, 1, 4, 7, 3, 3, 4])
+ /// [1, 4, 7, 3]
+ ///
+ pub fn unique(list: List(a)) -> List(a) {
+ case list {
+ [] -> []
+ [x, ..rest] -> [x, ..unique(filter(rest, fn(y) { y != x }))]
+ }
}
-}
-fn do_sort(
- list: List(a),
- compare: fn(a, a) -> Order,
- list_length: Int,
-) -> List(a) {
- case list_length < 2 {
- True -> list
- False -> {
- let split_length = list_length / 2
- let a_list = take(list, split_length)
- let b_list = drop(list, split_length)
- merge_sort(
- do_sort(a_list, compare, split_length),
- do_sort(b_list, compare, list_length - split_length),
- compare,
- )
+ fn merge_sort(a: List(a), b: List(a), compare: fn(a, a) -> Order) -> List(a) {
+ case a, b {
+ [], _ -> b
+ _, [] -> a
+ [ax, ..ar], [bx, ..br] ->
+ case compare(ax, bx) {
+ order.Lt -> [ax, ..merge_sort(ar, b, compare)]
+ _ -> [bx, ..merge_sort(a, br, compare)]
+ }
}
}
-}
-/// Sorts from smallest to largest based upon the ordering specified by a given
-/// function.
-///
-/// ## Examples
-///
-/// > import gleam/int
-/// > list.sort([4, 3, 6, 5, 4, 1, 2], by: int.compare)
-/// [1, 2, 3, 4, 4, 5, 6]
-///
-pub fn sort(list: List(a), by compare: fn(a, a) -> Order) -> List(a) {
- do_sort(list, compare, length(list))
-}
+ fn do_sort(
+ list: List(a),
+ compare: fn(a, a) -> Order,
+ list_length: Int,
+ ) -> List(a) {
+ case list_length < 2 {
+ True -> list
+ False -> {
+ let split_length = list_length / 2
+ let a_list = take(list, split_length)
+ let b_list = drop(list, split_length)
+ merge_sort(
+ do_sort(a_list, compare, split_length),
+ do_sort(b_list, compare, list_length - split_length),
+ compare,
+ )
+ }
+ }
+ }
-/// Creates a list of ints ranging from a given start and finish.
-///
-/// ## Examples
-///
-/// > range(0, 0)
-/// []
-///
-/// > range(0, 5)
-/// [0, 1, 2, 3, 4]
-///
-/// > range(1, -5)
-/// [1, 0, -1, -2, -3, -4]
-///
-pub fn range(from start: Int, to stop: Int) -> List(Int) {
- case int.compare(start, stop) {
- order.Eq -> []
- order.Gt -> [start, ..range(start - 1, stop)]
- order.Lt -> [start, ..range(start + 1, stop)]
+ /// Sorts from smallest to largest based upon the ordering specified by a given
+ /// function.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/int
+ /// > list.sort([4, 3, 6, 5, 4, 1, 2], by: int.compare)
+ /// [1, 2, 3, 4, 4, 5, 6]
+ ///
+ pub fn sort(list: List(a), by compare: fn(a, a) -> Order) -> List(a) {
+ do_sort(list, compare, length(list))
}
-}
-fn do_repeat(a: a, times: Int, acc: List(a)) -> List(a) {
- case times <= 0 {
- True -> acc
- False -> do_repeat(a, times - 1, [a, ..acc])
+ /// Creates a list of ints ranging from a given start and finish.
+ ///
+ /// ## Examples
+ ///
+ /// > range(0, 0)
+ /// []
+ ///
+ /// > range(0, 5)
+ /// [0, 1, 2, 3, 4]
+ ///
+ /// > range(1, -5)
+ /// [1, 0, -1, -2, -3, -4]
+ ///
+ pub fn range(from start: Int, to stop: Int) -> List(Int) {
+ case int.compare(start, stop) {
+ order.Eq -> []
+ order.Gt -> [start, ..range(start - 1, stop)]
+ order.Lt -> [start, ..range(start + 1, stop)]
+ }
}
-}
-/// Builds a list of a given value a given number of times.
-///
-/// ## Examples
-///
-/// > repeat("a", times: 0)
-/// []
-///
-/// > repeat("a", times: 5)
-/// ["a", "a", "a", "a", "a"]
-///
-pub fn repeat(item a: a, times times: Int) -> List(a) {
- do_repeat(a, times, [])
-}
+ fn do_repeat(a: a, times: Int, acc: List(a)) -> List(a) {
+ case times <= 0 {
+ True -> acc
+ False -> do_repeat(a, times - 1, [a, ..acc])
+ }
+ }
-fn do_split(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) {
- case n <= 0 {
- True -> #(reverse(taken), list)
- False ->
- case list {
- [] -> #(reverse(taken), [])
- [x, ..xs] -> do_split(xs, n - 1, [x, ..taken])
- }
+ /// Builds a list of a given value a given number of times.
+ ///
+ /// ## Examples
+ ///
+ /// > repeat("a", times: 0)
+ /// []
+ ///
+ /// > repeat("a", times: 5)
+ /// ["a", "a", "a", "a", "a"]
+ ///
+ pub fn repeat(item a: a, times times: Int) -> List(a) {
+ do_repeat(a, times, [])
}
-}
-/// Splits a list in two before the given index.
-///
-/// If the list is not long enough to have the given index the before list will
-/// be the input list, and the after list will be empty.
-///
-/// ## Examples
-///
-/// > split([6, 7, 8, 9], 0)
-/// #([], [6, 7, 8, 9])
-///
-/// > split([6, 7, 8, 9], 2)
-/// #([6, 7], [8, 9])
-///
-/// > split([6, 7, 8, 9], 4)
-/// #([6, 7, 8, 9], [])
-///
-pub fn split(list list: List(a), at index: Int) -> #(List(a), List(a)) {
- do_split(list, index, [])
-}
+ fn do_split(list: List(a), n: Int, taken: List(a)) -> #(List(a), List(a)) {
+ case n <= 0 {
+ True -> #(reverse(taken), list)
+ False ->
+ case list {
+ [] -> #(reverse(taken), [])
+ [x, ..xs] -> do_split(xs, n - 1, [x, ..taken])
+ }
+ }
+ }
-fn do_split_while(
- list: List(a),
- f: fn(a) -> Bool,
- acc: List(a),
-) -> #(List(a), List(a)) {
- case list {
- [] -> #(reverse(acc), [])
- [x, ..xs] ->
- case f(x) {
- False -> #(reverse(acc), list)
- _ -> do_split_while(xs, f, [x, ..acc])
- }
+ /// Splits a list in two before the given index.
+ ///
+ /// If the list is not long enough to have the given index the before list will
+ /// be the input list, and the after list will be empty.
+ ///
+ /// ## Examples
+ ///
+ /// > split([6, 7, 8, 9], 0)
+ /// #([], [6, 7, 8, 9])
+ ///
+ /// > split([6, 7, 8, 9], 2)
+ /// #([6, 7], [8, 9])
+ ///
+ /// > split([6, 7, 8, 9], 4)
+ /// #([6, 7, 8, 9], [])
+ ///
+ pub fn split(list list: List(a), at index: Int) -> #(List(a), List(a)) {
+ do_split(list, index, [])
}
-}
-/// Splits a list in two before the first element that a given function returns
-/// False for.
-///
-/// If the function returns True for all elements the first list will be the
-/// input list, and the second list will be empty.
-///
-/// ## Examples
-///
-/// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 })
-/// #([1, 2, 3], [4, 5])
-///
-/// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 })
-/// #([1, 2, 3, 4, 5], [])
-///
-pub fn split_while(
- list list: List(a),
- satisfying predicate: fn(a) -> Bool,
-) -> #(List(a), List(a)) {
- do_split_while(list, predicate, [])
-}
+ fn do_split_while(
+ list: List(a),
+ f: fn(a) -> Bool,
+ acc: List(a),
+ ) -> #(List(a), List(a)) {
+ case list {
+ [] -> #(reverse(acc), [])
+ [x, ..xs] ->
+ case f(x) {
+ False -> #(reverse(acc), list)
+ _ -> do_split_while(xs, f, [x, ..acc])
+ }
+ }
+ }
-/// Given a list of 2 element tuples, finds the first tuple that has a given
-/// key as the first element and returns the second element.
-///
-/// If no tuple is found with the given key then `Error(Nil)` is returned.
-///
-/// This function may be useful for interacting with Erlang code where lists of
-/// tuples are common.
-///
-/// ## Examples
-///
-/// > key_find([#("a", 0), #("b", 1)], "a")
-/// Ok(0)
-///
-/// > key_find([#("a", 0), #("b", 1)], "b")
-/// Ok(1)
-///
-/// > key_find([#("a", 0), #("b", 1)], "c")
-/// Error(Nil)
-///
-pub fn key_find(
- in keyword_list: List(#(k, v)),
- find desired_key: k,
-) -> Result(v, Nil) {
- find_map(
- keyword_list,
- fn(keyword) {
- let #(key, value) = keyword
- case key == desired_key {
- True -> Ok(value)
- False -> Error(Nil)
- }
- },
- )
-}
+ /// Splits a list in two before the first element that a given function returns
+ /// False for.
+ ///
+ /// If the function returns True for all elements the first list will be the
+ /// input list, and the second list will be empty.
+ ///
+ /// ## Examples
+ ///
+ /// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 })
+ /// #([1, 2, 3], [4, 5])
+ ///
+ /// > split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 })
+ /// #([1, 2, 3, 4, 5], [])
+ ///
+ pub fn split_while(
+ list list: List(a),
+ satisfying predicate: fn(a) -> Bool,
+ ) -> #(List(a), List(a)) {
+ do_split_while(list, predicate, [])
+ }
-fn do_pop(haystack, predicate, checked) {
- case haystack {
- [] -> Error(Nil)
- [x, ..rest] ->
- case predicate(x) {
- True -> Ok(#(x, append(reverse(checked), rest)))
- False -> do_pop(rest, predicate, [x, ..checked])
- }
+ /// Given a list of 2 element tuples, finds the first tuple that has a given
+ /// key as the first element and returns the second element.
+ ///
+ /// If no tuple is found with the given key then `Error(Nil)` is returned.
+ ///
+ /// This function may be useful for interacting with Erlang code where lists of
+ /// tuples are common.
+ ///
+ /// ## Examples
+ ///
+ /// > key_find([#("a", 0), #("b", 1)], "a")
+ /// Ok(0)
+ ///
+ /// > key_find([#("a", 0), #("b", 1)], "b")
+ /// Ok(1)
+ ///
+ /// > key_find([#("a", 0), #("b", 1)], "c")
+ /// Error(Nil)
+ ///
+ pub fn key_find(
+ in keyword_list: List(#(k, v)),
+ find desired_key: k,
+ ) -> Result(v, Nil) {
+ find_map(
+ keyword_list,
+ fn(keyword) {
+ let #(key, value) = keyword
+ case key == desired_key {
+ True -> Ok(value)
+ False -> Error(Nil)
+ }
+ },
+ )
}
-}
-/// Removes the first element in a given list for which the predicate funtion returns `True`.
-///
-/// Returns `Error(Nil)` if no the function does not return True for any of the
-/// elements.
-///
-/// ## Examples
-///
-/// > pop([1, 2, 3], fn(x) { x > 2 })
-/// Ok(#(3, [1, 2]))
-///
-/// > pop([1, 2, 3], fn(x) { x > 4 })
-/// Error(Nil)
-///
-/// > pop([], fn(x) { True })
-/// Error(Nil)
-///
-pub fn pop(
- in haystack: List(a),
- one_that is_desired: fn(a) -> Bool,
-) -> Result(#(a, List(a)), Nil) {
- do_pop(haystack, is_desired, [])
-}
+ fn do_pop(haystack, predicate, checked) {
+ case haystack {
+ [] -> Error(Nil)
+ [x, ..rest] ->
+ case predicate(x) {
+ True -> Ok(#(x, append(reverse(checked), rest)))
+ False -> do_pop(rest, predicate, [x, ..checked])
+ }
+ }
+ }
-fn do_pop_map(haystack, mapper, checked) {
- case haystack {
- [] -> Error(Nil)
- [x, ..rest] ->
- case mapper(x) {
- Ok(y) -> Ok(#(y, append(reverse(checked), rest)))
- Error(_) -> do_pop_map(rest, mapper, [x, ..checked])
- }
+ /// Removes the first element in a given list for which the predicate funtion returns `True`.
+ ///
+ /// Returns `Error(Nil)` if no the function does not return True for any of the
+ /// elements.
+ ///
+ /// ## Examples
+ ///
+ /// > pop([1, 2, 3], fn(x) { x > 2 })
+ /// Ok(#(3, [1, 2]))
+ ///
+ /// > pop([1, 2, 3], fn(x) { x > 4 })
+ /// Error(Nil)
+ ///
+ /// > pop([], fn(x) { True })
+ /// Error(Nil)
+ ///
+ pub fn pop(
+ in haystack: List(a),
+ one_that is_desired: fn(a) -> Bool,
+ ) -> Result(#(a, List(a)), Nil) {
+ do_pop(haystack, is_desired, [])
}
-}
-/// Removes the first element in a given list for which the given function returns
-/// `Ok(new_value)` and return the new value as well as list with the value removed.
-///
-/// Returns `Error(Nil)` if no the function does not return Ok for any of the
-/// elements.
-///
-/// ## Examples
-///
-/// > pop_map([[], [2], [3]], head)
-/// Ok(#(2, [[], [3]]))
-///
-/// > pop_map([[], []], head)
-/// Error(Nil)
-///
-/// > pop_map([], head)
-/// Error(Nil)
-///
-pub fn pop_map(
- in haystack: List(a),
- one_that is_desired: fn(a) -> Result(b, c),
-) -> Result(#(b, List(a)), Nil) {
- do_pop_map(haystack, is_desired, [])
-}
+ fn do_pop_map(haystack, mapper, checked) {
+ case haystack {
+ [] -> Error(Nil)
+ [x, ..rest] ->
+ case mapper(x) {
+ Ok(y) -> Ok(#(y, append(reverse(checked), rest)))
+ Error(_) -> do_pop_map(rest, mapper, [x, ..checked])
+ }
+ }
+ }
-/// Given a list of 2 element tuples, finds the first tuple that has a given
-/// key as the first element. This function will return the second element
-/// of the found tuple and list with tuple removed.
-///
-/// If no tuple is found with the given key then `Error(Nil)` is returned.
-///
-/// ## Examples
-///
-/// > key_pop([#("a", 0), #("b", 1)], "a")
-/// Ok(#(0, [#("b", 1)])
-///
-/// > key_pop([#("a", 0), #("b", 1)], "b")
-/// Ok(#(1, [#("a", 0)])
-///
-/// > key_pop([#("a", 0), #("b", 1)], "c")
-/// Error(Nil)
-///
-pub fn key_pop(
- haystack: List(#(k, v)),
- key: k,
-) -> Result(#(v, List(#(k, v))), Nil) {
- pop_map(
- haystack,
- fn(entry) {
- let #(k, v) = entry
- case k {
- k if k == key -> Ok(v)
- _ -> Error(Nil)
- }
- },
- )
-}
+ /// Removes the first element in a given list for which the given function returns
+ /// `Ok(new_value)` and return the new value as well as list with the value removed.
+ ///
+ /// Returns `Error(Nil)` if no the function does not return Ok for any of the
+ /// elements.
+ ///
+ /// ## Examples
+ ///
+ /// > pop_map([[], [2], [3]], head)
+ /// Ok(#(2, [[], [3]]))
+ ///
+ /// > pop_map([[], []], head)
+ /// Error(Nil)
+ ///
+ /// > pop_map([], head)
+ /// Error(Nil)
+ ///
+ pub fn pop_map(
+ in haystack: List(a),
+ one_that is_desired: fn(a) -> Result(b, c),
+ ) -> Result(#(b, List(a)), Nil) {
+ do_pop_map(haystack, is_desired, [])
+ }
-/// Given a list of 2 element tuples, inserts a key and value into the list.
-///
-/// If there was already a tuple with the key then it is replaced, otherwise it
-/// is added to the end of the list.
-///
-///
-/// ## Examples
-///
-/// > key_set([#(5, 0), #(4, 1)], 4, 100)
-/// [#(5, 0), #(4, 100)]
-///
-/// > key_set([#(5, 0), #(4, 1)], 1, 100)
-/// [#(5, 0), #(4, 1), #(1, 100)]
-///
-pub fn key_set(list: List(#(a, b)), key: a, value: b) -> List(#(a, b)) {
- case list {
- [] -> [#(key, value)]
- [#(k, _), ..rest] if k == key -> [#(key, value), ..rest]
- [first, ..rest] -> [first, ..key_set(rest, key, value)]
+ /// Given a list of 2 element tuples, finds the first tuple that has a given
+ /// key as the first element. This function will return the second element
+ /// of the found tuple and list with tuple removed.
+ ///
+ /// If no tuple is found with the given key then `Error(Nil)` is returned.
+ ///
+ /// ## Examples
+ ///
+ /// > key_pop([#("a", 0), #("b", 1)], "a")
+ /// Ok(#(0, [#("b", 1)])
+ ///
+ /// > key_pop([#("a", 0), #("b", 1)], "b")
+ /// Ok(#(1, [#("a", 0)])
+ ///
+ /// > key_pop([#("a", 0), #("b", 1)], "c")
+ /// Error(Nil)
+ ///
+ pub fn key_pop(
+ haystack: List(#(k, v)),
+ key: k,
+ ) -> Result(#(v, List(#(k, v))), Nil) {
+ pop_map(
+ haystack,
+ fn(entry) {
+ let #(k, v) = entry
+ case k {
+ k if k == key -> Ok(v)
+ _ -> Error(Nil)
+ }
+ },
+ )
}
-}
-/// Calls a function for each element in a list, discarding the results.
-///
-pub fn each(list: List(a), f: fn(a) -> b) -> Nil {
- case list {
- [] -> Nil
- [x, ..xs] -> {
- f(x)
- each(xs, f)
+ /// Given a list of 2 element tuples, inserts a key and value into the list.
+ ///
+ /// If there was already a tuple with the key then it is replaced, otherwise it
+ /// is added to the end of the list.
+ ///
+ ///
+ /// ## Examples
+ ///
+ /// > key_set([#(5, 0), #(4, 1)], 4, 100)
+ /// [#(5, 0), #(4, 100)]
+ ///
+ /// > key_set([#(5, 0), #(4, 1)], 1, 100)
+ /// [#(5, 0), #(4, 1), #(1, 100)]
+ ///
+ pub fn key_set(list: List(#(a, b)), key: a, value: b) -> List(#(a, b)) {
+ case list {
+ [] -> [#(key, value)]
+ [#(k, _), ..rest] if k == key -> [#(key, value), ..rest]
+ [first, ..rest] -> [first, ..key_set(rest, key, value)]
}
}
-}
-fn do_partition(list, categorise, trues, falses) {
- case list {
- [] -> #(reverse(trues), reverse(falses))
- [x, ..xs] ->
- case categorise(x) {
- True -> do_partition(xs, categorise, [x, ..trues], falses)
- False -> do_partition(xs, categorise, trues, [x, ..falses])
+ /// Calls a function for each element in a list, discarding the results.
+ ///
+ pub fn each(list: List(a), f: fn(a) -> b) -> Nil {
+ case list {
+ [] -> Nil
+ [x, ..xs] -> {
+ f(x)
+ each(xs, f)
}
+ }
}
-}
-pub fn partition(
- list: List(a),
- with categorise: fn(a) -> Bool,
-) -> #(List(a), List(a)) {
- do_partition(list, categorise, [], [])
-}
+ fn do_partition(list, categorise, trues, falses) {
+ case list {
+ [] -> #(reverse(trues), reverse(falses))
+ [x, ..xs] ->
+ case categorise(x) {
+ True -> do_partition(xs, categorise, [x, ..trues], falses)
+ False -> do_partition(xs, categorise, trues, [x, ..falses])
+ }
+ }
+ }
-/// Returns all the permutations of a list
-/// All values must be unique
-///
-/// ## Examples
-///
-/// > permutations([1, 2])
-/// [[1, 2], [2, 1]]
-///
-pub fn permutations(l: List(a)) -> List(List(a)) {
- case l {
- [] -> [[]]
- _ ->
- map(
- l,
- fn(x) {
- filter(l, fn(y) { y != x })
- |> permutations
- |> map(append([x], _))
- },
- )
- |> flatten
+ pub fn partition(
+ list: List(a),
+ with categorise: fn(a) -> Bool,
+ ) -> #(List(a), List(a)) {
+ do_partition(list, categorise, [], [])
}
-}
-fn do_window(acc: List(List(a)), l: List(a), n: Int) -> List(List(a)) {
- let window = take(l, n)
+ /// Returns all the permutations of a list
+ /// All values must be unique
+ ///
+ /// ## Examples
+ ///
+ /// > permutations([1, 2])
+ /// [[1, 2], [2, 1]]
+ ///
+ pub fn permutations(l: List(a)) -> List(List(a)) {
+ case l {
+ [] -> [[]]
+ _ ->
+ map(
+ l,
+ fn(x) {
+ filter(l, fn(y) { y != x })
+ |> permutations
+ |> map(append([x], _))
+ },
+ )
+ |> flatten
+ }
+ }
+
+ fn do_window(acc: List(List(a)), l: List(a), n: Int) -> List(List(a)) {
+ let window = take(l, n)
- case length(window) == n {
- True -> do_window([window, ..acc], drop(l, 1), n)
- False -> acc
+ case length(window) == n {
+ True -> do_window([window, ..acc], drop(l, 1), n)
+ False -> acc
+ }
}
-}
-/// Returns a list of sliding window
-///
-/// ## Examples
-///
-/// ```
-/// > window([1,2,3,4,5], 3)
-/// [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
-///
-/// > window([1, 2], 4)
-/// []
-/// ```
-///
-pub fn window(l: List(a), by n: Int) -> List(List(a)) {
- do_window([], l, n)
- |> reverse
-}
+ /// Returns a list of sliding window
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > window([1,2,3,4,5], 3)
+ /// [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
+ ///
+ /// > window([1, 2], 4)
+ /// []
+ /// ```
+ ///
+ pub fn window(l: List(a), by n: Int) -> List(List(a)) {
+ do_window([], l, n)
+ |> reverse
+ }
-/// Returns a list of tuples containing two contiguous elements
-///
-/// ## Examples
-///
-/// ```
-/// > window_by_2([1,2,3,4])
-/// [#(1, 2), #(2, 3), #(3, 4)]
-///
-/// > window_by_2([1])
-/// []
-/// ```
-///
-pub fn window_by_2(l: List(a)) -> List(#(a, a)) {
- zip(l, drop(l, 1))
-}
+ /// Returns a list of tuples containing two contiguous elements
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > window_by_2([1,2,3,4])
+ /// [#(1, 2), #(2, 3), #(3, 4)]
+ ///
+ /// > window_by_2([1])
+ /// []
+ /// ```
+ ///
+ pub fn window_by_2(l: List(a)) -> List(#(a, a)) {
+ zip(l, drop(l, 1))
+ }
-/// Drops the first elements in a given list for which the predicate funtion returns `True`.
-///
-/// ## Examples
-///
-/// > drop_while([1, 2, 3, 4], fun (x) { x < 3 })
-/// [3, 4]
-///
-pub fn drop_while(
- in list: List(a),
- satisfying predicate: fn(a) -> Bool,
-) -> List(a) {
- case list {
- [] -> []
- [x, ..xs] ->
- case predicate(x) {
- True -> drop_while(xs, predicate)
- False -> [x, ..xs]
- }
+ /// Drops the first elements in a given list for which the predicate funtion returns `True`.
+ ///
+ /// ## Examples
+ ///
+ /// > drop_while([1, 2, 3, 4], fun (x) { x < 3 })
+ /// [3, 4]
+ ///
+ pub fn drop_while(
+ in list: List(a),
+ satisfying predicate: fn(a) -> Bool,
+ ) -> List(a) {
+ case list {
+ [] -> []
+ [x, ..xs] ->
+ case predicate(x) {
+ True -> drop_while(xs, predicate)
+ False -> [x, ..xs]
+ }
+ }
}
-}
-fn do_take_while(
- list: List(a),
- predicate: fn(a) -> Bool,
- acc: List(a),
-) -> List(a) {
- case list {
- [] -> reverse(acc)
- [head, ..tail] ->
- case predicate(head) {
- True -> do_take_while(tail, predicate, [head, ..acc])
- False -> reverse(acc)
- }
+ fn do_take_while(
+ list: List(a),
+ predicate: fn(a) -> Bool,
+ acc: List(a),
+ ) -> List(a) {
+ case list {
+ [] -> reverse(acc)
+ [head, ..tail] ->
+ case predicate(head) {
+ True -> do_take_while(tail, predicate, [head, ..acc])
+ False -> reverse(acc)
+ }
+ }
}
-}
-/// Takes the first elements in a given list for which the predicate funtion returns `True`.
-///
-/// ## Examples
-///
-/// > take_while([1, 2, 3, 2, 4], fun (x) { x < 3 })
-/// [1, 2]
-///
-pub fn take_while(
- in list: List(a),
- satisfying predicate: fn(a) -> Bool,
-) -> List(a) {
- do_take_while(list, predicate, [])
-}
+ /// Takes the first elements in a given list for which the predicate funtion returns `True`.
+ ///
+ /// ## Examples
+ ///
+ /// > take_while([1, 2, 3, 2, 4], fun (x) { x < 3 })
+ /// [1, 2]
+ ///
+ pub fn take_while(
+ in list: List(a),
+ satisfying predicate: fn(a) -> Bool,
+ ) -> List(a) {
+ do_take_while(list, predicate, [])
+ }
-fn do_chunk(
- list: List(a),
- f: fn(a) -> key,
- previous_key: key,
- current_chunk: List(a),
- acc: List(List(a)),
-) -> List(List(a)) {
- case list {
- [] -> reverse([reverse(current_chunk), ..acc])
- [head, ..tail] -> {
- let key = f(head)
- case key == previous_key {
- False -> do_chunk(tail, f, key, [head], [reverse(current_chunk), ..acc])
- True -> do_chunk(tail, f, key, [head, ..current_chunk], acc)
+ fn do_chunk(
+ list: List(a),
+ f: fn(a) -> key,
+ previous_key: key,
+ current_chunk: List(a),
+ acc: List(List(a)),
+ ) -> List(List(a)) {
+ case list {
+ [] -> reverse([reverse(current_chunk), ..acc])
+ [head, ..tail] -> {
+ let key = f(head)
+ case key == previous_key {
+ False ->
+ do_chunk(tail, f, key, [head], [reverse(current_chunk), ..acc])
+ True -> do_chunk(tail, f, key, [head, ..current_chunk], acc)
+ }
}
}
}
-}
-/// Returns a list of chunks in which
-/// the result of calling `f` on each element is the same.
-///
-/// ## Examples
-///
-/// > [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 })
-/// [[1], [2, 2], [3], [4, 4, 6], [7, 7]]
-///
-pub fn chunk(in list: List(a), by f: fn(a) -> key) -> List(List(a)) {
- case list {
- [] -> []
- [head, ..tail] -> do_chunk(tail, f, f(head), [head], [])
+ /// Returns a list of chunks in which
+ /// the result of calling `f` on each element is the same.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 })
+ /// [[1], [2, 2], [3], [4, 4, 6], [7, 7]]
+ ///
+ pub fn chunk(in list: List(a), by f: fn(a) -> key) -> List(List(a)) {
+ case list {
+ [] -> []
+ [head, ..tail] -> do_chunk(tail, f, f(head), [head], [])
+ }
}
-}
-fn do_sized_chunk(
- list: List(a),
- count: Int,
- left: Int,
- current_chunk: List(a),
- acc: List(List(a)),
-) -> List(List(a)) {
- case list {
- [] ->
- case current_chunk {
- [] -> reverse(acc)
- remaining -> reverse([reverse(remaining), ..acc])
- }
- [head, ..tail] -> {
- let chunk = [head, ..current_chunk]
- case left > 1 {
- False -> do_sized_chunk(tail, count, count, [], [reverse(chunk), ..acc])
- True -> do_sized_chunk(tail, count, left - 1, chunk, acc)
+ fn do_sized_chunk(
+ list: List(a),
+ count: Int,
+ left: Int,
+ current_chunk: List(a),
+ acc: List(List(a)),
+ ) -> List(List(a)) {
+ case list {
+ [] ->
+ case current_chunk {
+ [] -> reverse(acc)
+ remaining -> reverse([reverse(remaining), ..acc])
+ }
+ [head, ..tail] -> {
+ let chunk = [head, ..current_chunk]
+ case left > 1 {
+ False ->
+ do_sized_chunk(tail, count, count, [], [reverse(chunk), ..acc])
+ True -> do_sized_chunk(tail, count, left - 1, chunk, acc)
+ }
}
}
}
-}
-/// Returns a list of chunks containing `count` elements each.
-///
-/// If the last chunk does not have `count` elements, it is instead
-/// a partial chunk, with less than `count` elements.
-///
-/// For any `count` less than 1 this function behaves as if it was set to 1.
-///
-/// ## Examples
-///
-/// > [1, 2, 3, 4, 5, 6] |> chunk(into: 2)
-/// [[1, 2], [3, 4], [5, 6]]
-///
-/// > [1, 2, 3, 4, 5, 6, 7, 8] |> chunk(into: 3)
-/// [[1, 2, 3], [4, 5, 6], [7, 8]]
-///
-pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) {
- do_sized_chunk(list, count, count, [], [])
-}
+ /// Returns a list of chunks containing `count` elements each.
+ ///
+ /// If the last chunk does not have `count` elements, it is instead
+ /// a partial chunk, with less than `count` elements.
+ ///
+ /// For any `count` less than 1 this function behaves as if it was set to 1.
+ ///
+ /// ## Examples
+ ///
+ /// > [1, 2, 3, 4, 5, 6] |> chunk(into: 2)
+ /// [[1, 2], [3, 4], [5, 6]]
+ ///
+ /// > [1, 2, 3, 4, 5, 6, 7, 8] |> chunk(into: 3)
+ /// [[1, 2, 3], [4, 5, 6], [7, 8]]
+ ///
+ pub fn sized_chunk(in list: List(a), into count: Int) -> List(List(a)) {
+ do_sized_chunk(list, count, count, [], [])
+ }
-/// This function acts similar to fold, but does not take an initial state.
-/// Instead, it starts from the first element in the list
-/// and combines it with each subsequent element in turn using the given function.
-/// The function is called as fun(current_element, accumulator).
-///
-/// Returns `Ok` to indicate a successful run, and `Error` if called on an empty list.
-///
-/// ## Examples
-///
-/// > [] |> reduce(fn(x, y) { x + y })
-/// Error(Nil)
-///
-/// > [1, 2, 3, 4, 5] |> reduce(fn(x, y) { x + y })
-/// Ok(15)
-///
-pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) {
- case list {
- [] -> Error(Nil)
- [head, ..tail] ->
- fold(tail, head, fun)
- |> Ok
+ /// This function acts similar to fold, but does not take an initial state.
+ /// Instead, it starts from the first element in the list
+ /// and combines it with each subsequent element in turn using the given function.
+ /// The function is called as fun(current_element, accumulator).
+ ///
+ /// Returns `Ok` to indicate a successful run, and `Error` if called on an empty list.
+ ///
+ /// ## Examples
+ ///
+ /// > [] |> reduce(fn(x, y) { x + y })
+ /// Error(Nil)
+ ///
+ /// > [1, 2, 3, 4, 5] |> reduce(fn(x, y) { x + y })
+ /// Ok(15)
+ ///
+ pub fn reduce(over list: List(a), with fun: fn(a, a) -> a) -> Result(a, Nil) {
+ case list {
+ [] -> Error(Nil)
+ [head, ..tail] ->
+ fold(tail, head, fun)
+ |> Ok
+ }
}
-}
-fn do_scan(
- list: List(a),
- accumulator: b,
- accumulated: List(b),
- fun: fn(a, b) -> b,
-) -> List(b) {
- case list {
- [] -> reverse(accumulated)
- [x, ..xs] -> {
- let next = fun(x, accumulator)
- do_scan(xs, next, [next, ..accumulated], fun)
+ fn do_scan(
+ list: List(a),
+ accumulator: b,
+ accumulated: List(b),
+ fun: fn(a, b) -> b,
+ ) -> List(b) {
+ case list {
+ [] -> reverse(accumulated)
+ [x, ..xs] -> {
+ let next = fun(x, accumulator)
+ do_scan(xs, next, [next, ..accumulated], fun)
+ }
}
}
-}
-/// Similar to `fold`, but yields the state of the accumulator at each stage.
-///
-/// ## Examples
-///
-/// > scan(over: [1, 2, 3], from: 100, with: fn(i, acc) { acc + i })
-/// [101, 103, 106]
-///
-pub fn scan(
- over list: List(a),
- from initial: b,
- with fun: fn(a, b) -> b,
-) -> List(b) {
- do_scan(list, initial, [], fun)
-}
+ /// Similar to `fold`, but yields the state of the accumulator at each stage.
+ ///
+ /// ## Examples
+ ///
+ /// > scan(over: [1, 2, 3], from: 100, with: fn(i, acc) { acc + i })
+ /// [101, 103, 106]
+ ///
+ pub fn scan(
+ over list: List(a),
+ from initial: b,
+ with fun: fn(a, b) -> b,
+ ) -> List(b) {
+ do_scan(list, initial, [], fun)
+ }
-/// Returns the last element in the given list.
-///
-/// Returns `Error(Nil)` if the list is empty.
-///
-/// This function runs in linear time.
-/// For a collection oriented around performant access at either end,
-/// see `gleam/queue.Queue`.
-///
-/// ## Examples
-///
-/// > last([])
-/// Error(Nil)
-///
-/// > last([1, 2, 3, 4, 5])
-/// Ok(5)
-///
-pub fn last(list: List(a)) -> Result(a, Nil) {
- list
- |> reduce(fn(elem, _) { elem })
-}
+ /// Returns the last element in the given list.
+ ///
+ /// Returns `Error(Nil)` if the list is empty.
+ ///
+ /// This function runs in linear time.
+ /// For a collection oriented around performant access at either end,
+ /// see `gleam/queue.Queue`.
+ ///
+ /// ## Examples
+ ///
+ /// > last([])
+ /// Error(Nil)
+ ///
+ /// > last([1, 2, 3, 4, 5])
+ /// Ok(5)
+ ///
+ pub fn last(list: List(a)) -> Result(a, Nil) {
+ list
+ |> reduce(fn(elem, _) { elem })
+ }
-/// Return unique combinations of elements in the list
-///
-/// ## Examples
-///
-/// ```
-/// > combinations([1, 2, 3], 2)
-/// [[1, 2], [1, 3], [2, 3]]
-///
-/// > combinations([1, 2, 3, 4], 3)
-/// [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
-/// ```
-///
-pub fn combinations(items: List(a), by n: Int) -> List(List(a)) {
- case n {
- 0 -> [[]]
- _ ->
- case items {
- [] -> []
- [x, ..xs] -> {
- let first_combinations =
- map(combinations(xs, n - 1), with: fn(com) { [x, ..com] })
- |> reverse
- fold(
- first_combinations,
- combinations(xs, n),
- fn(c, acc) { [c, ..acc] },
- )
+ /// Return unique combinations of elements in the list
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > combinations([1, 2, 3], 2)
+ /// [[1, 2], [1, 3], [2, 3]]
+ ///
+ /// > combinations([1, 2, 3, 4], 3)
+ /// [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
+ /// ```
+ ///
+ pub fn combinations(items: List(a), by n: Int) -> List(List(a)) {
+ case n {
+ 0 -> [[]]
+ _ ->
+ case items {
+ [] -> []
+ [x, ..xs] -> {
+ let first_combinations =
+ map(combinations(xs, n - 1), with: fn(com) { [x, ..com] })
+ |> reverse
+ fold(
+ first_combinations,
+ combinations(xs, n),
+ fn(c, acc) { [c, ..acc] },
+ )
+ }
}
- }
+ }
}
-}
-fn do_combination_pairs(items: List(a)) -> List(List(#(a, a))) {
- case items {
- [] -> []
- [x, ..xs] -> {
- let first_combinations = map(xs, with: fn(other) { #(x, other) })
- [first_combinations, ..do_combination_pairs(xs)]
+ fn do_combination_pairs(items: List(a)) -> List(List(#(a, a))) {
+ case items {
+ [] -> []
+ [x, ..xs] -> {
+ let first_combinations = map(xs, with: fn(other) { #(x, other) })
+ [first_combinations, ..do_combination_pairs(xs)]
+ }
}
}
-}
-/// Return unique pair combinations of elements in the list
-///
-/// ## Examples
-///
-/// ```
-/// > combination_pairs([1, 2, 3])
-/// [#(1, 2), #(1, 3), #(2, 3)]
-/// ```
-///
-pub fn combination_pairs(items: List(a)) -> List(#(a, a)) {
- do_combination_pairs(items)
- |> flatten
-}
+ /// Return unique pair combinations of elements in the list
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > combination_pairs([1, 2, 3])
+ /// [#(1, 2), #(1, 3), #(2, 3)]
+ /// ```
+ ///
+ pub fn combination_pairs(items: List(a)) -> List(#(a, a)) {
+ do_combination_pairs(items)
+ |> flatten
+ }
-/// Make a list alternating the elements from the given lists
-///
-/// ## Examples
-///
-/// ```
-/// > list.interleave([[1, 2], [101, 102], [201, 202]])
-/// [1, 101, 201, 2, 102, 202]
-/// ```
-///
-pub fn interleave(list: List(List(a))) -> List(a) {
- transpose(list)
- |> flatten
-}
+ /// Make a list alternating the elements from the given lists
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > list.interleave([[1, 2], [101, 102], [201, 202]])
+ /// [1, 101, 201, 2, 102, 202]
+ /// ```
+ ///
+ pub fn interleave(list: List(List(a))) -> List(a) {
+ transpose(list)
+ |> flatten
+ }
-/// Transpose rows and columns of the list of lists.
-///
-/// ## Examples
-///
-/// ```
-/// > transpose([[1, 2, 3], [101, 102, 103]])
-/// [[1, 101], [2, 102], [3, 103]]
-/// ```
-pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) {
- let take_first = fn(list) {
- case list {
- [] -> []
- [f] -> [f]
- [f, .._rest] -> [f]
+ /// Transpose rows and columns of the list of lists.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > transpose([[1, 2, 3], [101, 102, 103]])
+ /// [[1, 101], [2, 102], [3, 103]]
+ /// ```
+ pub fn transpose(list_of_list: List(List(a))) -> List(List(a)) {
+ let take_first = fn(list) {
+ case list {
+ [] -> []
+ [f] -> [f]
+ [f, .._rest] -> [f]
+ }
}
- }
- case list_of_list {
- [] -> []
- [[], ..xss] -> transpose(xss)
- rows -> {
- let firsts =
- rows
- |> map(take_first)
- |> flatten
- let rest = transpose(map(rows, drop(_, 1)))
- [firsts, ..rest]
+ case list_of_list {
+ [] -> []
+ [[], ..xss] -> transpose(xss)
+ rows -> {
+ let firsts =
+ rows
+ |> map(take_first)
+ |> flatten
+ let rest = transpose(map(rows, drop(_, 1)))
+ [firsts, ..rest]
+ }
}
}
}
diff --git a/src/gleam/map.gleam b/src/gleam/map.gleam
index d51a78e..ff8281d 100644
--- a/src/gleam/map.gleam
+++ b/src/gleam/map.gleam
@@ -1,321 +1,327 @@
-import gleam/result
-import gleam/list
+if erlang {
+ import gleam/result
+ import gleam/list
-/// A dictionary of keys and values.
-///
-/// Any type can be used for the keys and values of a map, but all the keys
-/// must be of the same type and all the values must be of the same type.
-///
-/// Each key can only be present in a map once.
-///
-/// Maps are not ordered in any way, and any unintentional ordering is not to
-/// be relied upon in your code as it may change in future versions of Erlang
-/// or Gleam.
-///
-/// See [the Erlang map module](https://erlang.org/doc/man/maps.html) for more
-/// information.
-///
-pub external type Map(key, value)
+ /// A dictionary of keys and values.
+ ///
+ /// Any type can be used for the keys and values of a map, but all the keys
+ /// must be of the same type and all the values must be of the same type.
+ ///
+ /// Each key can only be present in a map once.
+ ///
+ /// Maps are not ordered in any way, and any unintentional ordering is not to
+ /// be relied upon in your code as it may change in future versions of Erlang
+ /// or Gleam.
+ ///
+ /// See [the Erlang map module](https://erlang.org/doc/man/maps.html) for more
+ /// information.
+ ///
+ pub external type Map(key, value)
-/// Determines the number of key-value pairs in the map.
-/// This function runs in constant time and does not need to iterate the map.
-///
-/// ## Examples
-///
-/// > new() |> size()
-/// 0
-///
-/// > new() |> insert("key", "value") |> size()
-/// 1
-///
-///
-pub external fn size(Map(k, v)) -> Int =
- "maps" "size"
+ /// Determines the number of key-value pairs in the map.
+ /// This function runs in constant time and does not need to iterate the map.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> size()
+ /// 0
+ ///
+ /// > new() |> insert("key", "value") |> size()
+ /// 1
+ ///
+ ///
+ pub external fn size(Map(k, v)) -> Int =
+ "maps" "size"
-/// Converts the map to a list of 2-element tuples `#(key, value)`, one for
-/// each key-value pair in the map.
-///
-/// The tuples in the list have no specific order.
-///
-/// ## Examples
-///
-/// > new() |> to_list()
-/// []
-///
-/// > new() |> insert("key", 0) |> to_list()
-/// [#("key", 0)]
-///
-pub external fn to_list(Map(key, value)) -> List(#(key, value)) =
- "maps" "to_list"
+ /// Converts the map to a list of 2-element tuples `#(key, value)`, one for
+ /// each key-value pair in the map.
+ ///
+ /// The tuples in the list have no specific order.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> to_list()
+ /// []
+ ///
+ /// > new() |> insert("key", 0) |> to_list()
+ /// [#("key", 0)]
+ ///
+ pub external fn to_list(Map(key, value)) -> List(#(key, value)) =
+ "maps" "to_list"
-/// Converts a list of 2-element tuples `#(key, value)` to a map.
-///
-/// If two tuples have the same key the last one in the list will be the one
-/// that is present in the map.
-///
-pub external fn from_list(List(#(key, value))) -> Map(key, value) =
- "maps" "from_list"
+ /// Converts a list of 2-element tuples `#(key, value)` to a map.
+ ///
+ /// If two tuples have the same key the last one in the list will be the one
+ /// that is present in the map.
+ ///
+ pub external fn from_list(List(#(key, value))) -> Map(key, value) =
+ "maps" "from_list"
-external fn is_key(key, Map(key, v)) -> Bool =
- "maps" "is_key"
+ external fn is_key(key, Map(key, v)) -> Bool =
+ "maps" "is_key"
-/// Determines whether or not a value present in the map for a given key.
-///
-/// ## Examples
-///
-/// > new() |> insert("a", 0) |> has_key("a")
-/// True
-///
-/// > new() |> insert("a", 0) |> has_key("b")
-/// False
-///
-pub fn has_key(map: Map(k, v), key: k) -> Bool {
- is_key(key, map)
-}
+ /// Determines whether or not a value present in the map for a given key.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert("a", 0) |> has_key("a")
+ /// True
+ ///
+ /// > new() |> insert("a", 0) |> has_key("b")
+ /// False
+ ///
+ pub fn has_key(map: Map(k, v), key: k) -> Bool {
+ is_key(key, map)
+ }
-/// Creates a fresh map that contains no values.
-///
-pub external fn new() -> Map(key, value) =
- "maps" "new"
+ /// Creates a fresh map that contains no values.
+ ///
+ pub external fn new() -> Map(key, value) =
+ "maps" "new"
-/// Fetches a value from a map for a given key.
-///
-/// The map may not have a value for the key, so the value is wrapped in a
-/// Result.
-///
-/// ## Examples
-///
-/// > new() |> insert("a", 0) |> get("a")
-/// Ok(0)
-///
-/// > new() |> insert("a", 0) |> get("b")
-/// Error(Nil)
-///
-pub external fn get(from: Map(key, value), get: key) -> Result(value, Nil) =
- "gleam_stdlib" "map_get"
+ /// Fetches a value from a map for a given key.
+ ///
+ /// The map may not have a value for the key, so the value is wrapped in a
+ /// Result.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert("a", 0) |> get("a")
+ /// Ok(0)
+ ///
+ /// > new() |> insert("a", 0) |> get("b")
+ /// Error(Nil)
+ ///
+ pub external fn get(from: Map(key, value), get: key) -> Result(value, Nil) =
+ "gleam_stdlib" "map_get"
-external fn erl_insert(key, value, Map(key, value)) -> Map(key, value) =
- "maps" "put"
+ external fn erl_insert(key, value, Map(key, value)) -> Map(key, value) =
+ "maps" "put"
-/// Inserts a value into the map with the given key.
-///
-/// If the map already has a value for the given key then the value is
-/// replaced with the new value.
-///
-/// ## Examples
-///
-/// > new() |> insert("a", 0) |> to_list
-/// [#("a", 0)]
-///
-/// > new() |> insert("a", 0) |> insert("a", 5) |> to_list
-/// [#("a", 5)]
-///
-pub fn insert(into map: Map(k, v), for key: k, insert value: v) -> Map(k, v) {
- erl_insert(key, value, map)
-}
+ /// Inserts a value into the map with the given key.
+ ///
+ /// If the map already has a value for the given key then the value is
+ /// replaced with the new value.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert("a", 0) |> to_list
+ /// [#("a", 0)]
+ ///
+ /// > new() |> insert("a", 0) |> insert("a", 5) |> to_list
+ /// [#("a", 5)]
+ ///
+ pub fn insert(into map: Map(k, v), for key: k, insert value: v) -> Map(k, v) {
+ erl_insert(key, value, map)
+ }
-external fn erl_map_values(fn(key, a) -> b, Map(key, value)) -> Map(key, b) =
- "maps" "map"
+ external fn erl_map_values(fn(key, a) -> b, Map(key, value)) -> Map(key, b) =
+ "maps" "map"
-/// Updates all values in a given map by calling a given function on each key
-/// and value.
-///
-/// ## Examples
-///
-/// > [#(3, 3), #(2, 4)]
-/// > |> from_list
-/// > |> map_values(fn(key, value) { key * value })
-/// [#(3, 9), #(2, 8)]
-///
-///
-pub fn map_values(in map: Map(k, v), with fun: fn(k, v) -> w) -> Map(k, w) {
- erl_map_values(fun, map)
-}
+ /// Updates all values in a given map by calling a given function on each key
+ /// and value.
+ ///
+ /// ## Examples
+ ///
+ /// > [#(3, 3), #(2, 4)]
+ /// > |> from_list
+ /// > |> map_values(fn(key, value) { key * value })
+ /// [#(3, 9), #(2, 8)]
+ ///
+ ///
+ pub fn map_values(in map: Map(k, v), with fun: fn(k, v) -> w) -> Map(k, w) {
+ erl_map_values(fun, map)
+ }
-/// Gets a list of all keys in a given map.
-///
-/// Maps are not ordered so the keys are not returned in any specific order. Do
-/// not write code that relies on the order keys are returned by this function
-/// as it may change in later versions of Gleam or Erlang.
-///
-/// ## Examples
-///
-/// > keys([#("a", 0), #("b", 1)])
-/// ["a", "b"]
-///
-pub external fn keys(Map(keys, v)) -> List(keys) =
- "maps" "keys"
+ /// Gets a list of all keys in a given map.
+ ///
+ /// Maps are not ordered so the keys are not returned in any specific order. Do
+ /// not write code that relies on the order keys are returned by this function
+ /// as it may change in later versions of Gleam or Erlang.
+ ///
+ /// ## Examples
+ ///
+ /// > keys([#("a", 0), #("b", 1)])
+ /// ["a", "b"]
+ ///
+ pub external fn keys(Map(keys, v)) -> List(keys) =
+ "maps" "keys"
-/// Gets a list of all values in a given map.
-///
-/// Maps are not ordered so the values are not returned in any specific order. Do
-/// not write code that relies on the order values are returned by this function
-/// as it may change in later versions of Gleam or Erlang.
-///
-/// ## Examples
-///
-/// > keys(from_list([#("a", 0), #("b", 1)]))
-/// [0, 1]
-///
-pub external fn values(Map(k, values)) -> List(values) =
- "maps" "values"
+ /// Gets a list of all values in a given map.
+ ///
+ /// Maps are not ordered so the values are not returned in any specific order. Do
+ /// not write code that relies on the order values are returned by this function
+ /// as it may change in later versions of Gleam or Erlang.
+ ///
+ /// ## Examples
+ ///
+ /// > keys(from_list([#("a", 0), #("b", 1)]))
+ /// [0, 1]
+ ///
+ pub external fn values(Map(k, values)) -> List(values) =
+ "maps" "values"
-external fn erl_filter(
- fn(key, value) -> Bool,
- Map(key, value),
-) -> Map(key, value) =
- "maps" "filter"
+ external fn erl_filter(
+ fn(key, value) -> Bool,
+ Map(key, value),
+ ) -> Map(key, value) =
+ "maps" "filter"
-/// Creates a new map from a given map, minus any entries that a given function
-/// returns False for.
-///
-/// ## Examples
-///
-/// > from_list([#("a", 0), #("b", 1)])
-/// > |> filter(fn(key, value) { value != 0 })
-/// from_list([#("b", 1)])
-///
-/// > from_list([#("a", 0), #("b", 1)])
-/// > |> filter(fn(key, value) { True })
-/// from_list([#("a", 0), #("b", 1)])
-///
-pub fn filter(in map: Map(k, v), for property: fn(k, v) -> Bool) -> Map(k, v) {
- erl_filter(property, map)
-}
+ /// Creates a new map from a given map, minus any entries that a given function
+ /// returns False for.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([#("a", 0), #("b", 1)])
+ /// > |> filter(fn(key, value) { value != 0 })
+ /// from_list([#("b", 1)])
+ ///
+ /// > from_list([#("a", 0), #("b", 1)])
+ /// > |> filter(fn(key, value) { True })
+ /// from_list([#("a", 0), #("b", 1)])
+ ///
+ pub fn filter(in map: Map(k, v), for property: fn(k, v) -> Bool) -> Map(k, v) {
+ erl_filter(property, map)
+ }
-external fn erl_take(List(k), Map(k, v)) -> Map(k, v) =
- "maps" "with"
+ external fn erl_take(List(k), Map(k, v)) -> Map(k, v) =
+ "maps" "with"
-/// Creates a new map from a given map, only including any entries for which the
-/// keys are in a given list.
-///
-/// ## Examples
-///
-/// > from_list([#("a", 0), #("b", 1)])
-/// > |> take(["b"])
-/// from_list([#("b", 1)])
-///
-/// > from_list([#("a", 0), #("b", 1)])
-/// > |> take(["a", "b", "c"])
-/// from_list([#("a", 0), #("b", 1)])
-///
-pub fn take(from map: Map(k, v), keeping desired_keys: List(k)) -> Map(k, v) {
- erl_take(desired_keys, map)
-}
+ /// Creates a new map from a given map, only including any entries for which the
+ /// keys are in a given list.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([#("a", 0), #("b", 1)])
+ /// > |> take(["b"])
+ /// from_list([#("b", 1)])
+ ///
+ /// > from_list([#("a", 0), #("b", 1)])
+ /// > |> take(["a", "b", "c"])
+ /// from_list([#("a", 0), #("b", 1)])
+ ///
+ pub fn take(from map: Map(k, v), keeping desired_keys: List(k)) -> Map(k, v) {
+ erl_take(desired_keys, map)
+ }
-/// Creates a new map from a pair of given maps by combining their entries.
-///
-/// If there are entries with the same keys in both maps the entry from the
-/// second map takes precedence.
-///
-/// ## Examples
-///
-/// > let a = from_list([#("a", 0), #("b", 1)])
-/// > let b = from_list([#("b", 2), #("c", 3)])
-/// > merge(a, b)
-/// from_list([#("a", 0), #("b", 2), #("c", 3)])
-///
-pub external fn merge(into: Map(k, v), merge: Map(k, v)) -> Map(k, v) =
- "maps" "merge"
+ /// Creates a new map from a pair of given maps by combining their entries.
+ ///
+ /// If there are entries with the same keys in both maps the entry from the
+ /// second map takes precedence.
+ ///
+ /// ## Examples
+ ///
+ /// > let a = from_list([#("a", 0), #("b", 1)])
+ /// > let b = from_list([#("b", 2), #("c", 3)])
+ /// > merge(a, b)
+ /// from_list([#("a", 0), #("b", 2), #("c", 3)])
+ ///
+ pub external fn merge(into: Map(k, v), merge: Map(k, v)) -> Map(k, v) =
+ "maps" "merge"
-external fn erl_delete(k, Map(k, v)) -> Map(k, v) =
- "maps" "remove"
+ external fn erl_delete(k, Map(k, v)) -> Map(k, v) =
+ "maps" "remove"
-/// Creates a new map from a given map with all the same entries except for the
-/// one with a given key, if it exists.
-///
-/// ## Examples
-///
-/// > delete([#("a", 0), #("b", 1)], "a")
-/// from_list([#("b", 1)])
-///
-/// > delete([#("a", 0), #("b", 1)], "c")
-/// from_list([#("a", 0), #("b", 1)])
-///
-pub fn delete(from map: Map(k, v), delete key: k) -> Map(k, v) {
- erl_delete(key, map)
-}
+ /// Creates a new map from a given map with all the same entries except for the
+ /// one with a given key, if it exists.
+ ///
+ /// ## Examples
+ ///
+ /// > delete([#("a", 0), #("b", 1)], "a")
+ /// from_list([#("b", 1)])
+ ///
+ /// > delete([#("a", 0), #("b", 1)], "c")
+ /// from_list([#("a", 0), #("b", 1)])
+ ///
+ pub fn delete(from map: Map(k, v), delete key: k) -> Map(k, v) {
+ erl_delete(key, map)
+ }
-/// Creates a new map from a given map with all the same entries except any with
-/// keys found in a given list.
-///
-/// ## Examples
-///
-/// > drop([#("a", 0), #("b", 1)], ["a"])
-/// from_list([#("b", 2)])
-///
-/// > delete([#("a", 0), #("b", 1)], ["c"])
-/// from_list([#("a", 0), #("b", 1)])
-///
-/// > drop([#("a", 0), #("b", 1)], ["a", "b", "c"])
-/// from_list([])
-///
-pub fn drop(from map: Map(k, v), drop disallowed_keys: List(k)) -> Map(k, v) {
- list.fold(disallowed_keys, map, fn(key, acc) { delete(acc, key) })
-}
+ /// Creates a new map from a given map with all the same entries except any with
+ /// keys found in a given list.
+ ///
+ /// ## Examples
+ ///
+ /// > drop([#("a", 0), #("b", 1)], ["a"])
+ /// from_list([#("b", 2)])
+ ///
+ /// > delete([#("a", 0), #("b", 1)], ["c"])
+ /// from_list([#("a", 0), #("b", 1)])
+ ///
+ /// > drop([#("a", 0), #("b", 1)], ["a", "b", "c"])
+ /// from_list([])
+ ///
+ pub fn drop(from map: Map(k, v), drop disallowed_keys: List(k)) -> Map(k, v) {
+ list.fold(disallowed_keys, map, fn(key, acc) { delete(acc, key) })
+ }
-/// Creates a new map with one entry updated using a given function.
-///
-/// If there was not an entry in the map for the given key then the function
-/// gets `Error(Nil)` as its argument, otherwise it gets `Ok(value)`.
-///
-/// ## Example
-///
-/// > let increment = fn(x) {
-/// > case x {
-/// > Ok(i) -> i + 1
-/// > Error(Nil) -> 0
-/// > }
-/// > }
-/// > let map = from_list([#("a", 0)])
-/// >
-/// > update(map, "a" increment)
-/// from_list([#("a", 1)])
-///
-/// > update(map, "b" increment)
-/// from_list([#("a", 0), #("b", 0)])
-///
-pub fn update(
- in map: Map(k, v),
- update key: k,
- with fun: fn(Result(v, Nil)) -> v,
-) -> Map(k, v) {
- map
- |> get(key)
- |> fun
- |> insert(map, key, _)
-}
+ /// Creates a new map with one entry updated using a given function.
+ ///
+ /// If there was not an entry in the map for the given key then the function
+ /// gets `Error(Nil)` as its argument, otherwise it gets `Ok(value)`.
+ ///
+ /// ## Example
+ ///
+ /// > let increment = fn(x) {
+ /// > case x {
+ /// > Ok(i) -> i + 1
+ /// > Error(Nil) -> 0
+ /// > }
+ /// > }
+ /// > let map = from_list([#("a", 0)])
+ /// >
+ /// > update(map, "a" increment)
+ /// from_list([#("a", 1)])
+ ///
+ /// > update(map, "b" increment)
+ /// from_list([#("a", 0), #("b", 0)])
+ ///
+ pub fn update(
+ in map: Map(k, v),
+ update key: k,
+ with fun: fn(Result(v, Nil)) -> v,
+ ) -> Map(k, v) {
+ map
+ |> get(key)
+ |> fun
+ |> insert(map, key, _)
+ }
-fn do_fold(list: List(#(k, v)), initial: acc, fun: fn(k, v, acc) -> acc) -> acc {
- case list {
- [] -> initial
- [#(k, v), ..tail] -> do_fold(tail, fun(k, v, initial), fun)
+ fn do_fold(
+ list: List(#(k, v)),
+ initial: acc,
+ fun: fn(k, v, acc) -> acc,
+ ) -> acc {
+ case list {
+ [] -> initial
+ [#(k, v), ..tail] -> do_fold(tail, fun(k, v, initial), fun)
+ }
}
-}
-/// Combines all entries into a single value by calling a given function on each
-/// one.
-///
-/// Maps are not ordered so the values are not returned in any specific order. Do
-/// not write code that relies on the order entries are used by this function
-/// as it may change in later versions of Gleam or Erlang.
-///
-/// # Examples
-///
-/// > let map = from_list([#("a", 1), #("b", 3), #("c", 9)])
-/// > fold(map, 0, fn(key, value, accumulator) { accumulator + value })
-/// 13
-///
-/// > import gleam/string.{append}
-/// > fold(map, "", fn(key, value, accumulator) { append(accumulator, value) })
-/// "abc"
-///
-pub fn fold(
- over map: Map(k, v),
- from initial: acc,
- with fun: fn(k, v, acc) -> acc,
-) -> acc {
- map
- |> to_list
- |> do_fold(initial, fun)
+ /// Combines all entries into a single value by calling a given function on each
+ /// one.
+ ///
+ /// Maps are not ordered so the values are not returned in any specific order. Do
+ /// not write code that relies on the order entries are used by this function
+ /// as it may change in later versions of Gleam or Erlang.
+ ///
+ /// # Examples
+ ///
+ /// > let map = from_list([#("a", 1), #("b", 3), #("c", 9)])
+ /// > fold(map, 0, fn(key, value, accumulator) { accumulator + value })
+ /// 13
+ ///
+ /// > import gleam/string.{append}
+ /// > fold(map, "", fn(key, value, accumulator) { append(accumulator, value) })
+ /// "abc"
+ ///
+ pub fn fold(
+ over map: Map(k, v),
+ from initial: acc,
+ with fun: fn(k, v, acc) -> acc,
+ ) -> acc {
+ map
+ |> to_list
+ |> do_fold(initial, fun)
+ }
}
diff --git a/src/gleam/option.gleam b/src/gleam/option.gleam
index f72f552..feb6f56 100644
--- a/src/gleam/option.gleam
+++ b/src/gleam/option.gleam
@@ -1,225 +1,227 @@
-import gleam/list
+if erlang {
+ 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/src/gleam/order.gleam b/src/gleam/order.gleam
index c030db4..ee81a62 100644
--- a/src/gleam/order.gleam
+++ b/src/gleam/order.gleam
@@ -1,101 +1,103 @@
-/// Represents the result of a single comparison to determine the precise
-/// ordering of two values.
-///
-pub type Order {
- /// Less-than
- Lt
+if erlang {
+ /// Represents the result of a single comparison to determine the precise
+ /// ordering of two values.
+ ///
+ pub type Order {
+ /// Less-than
+ Lt
- /// Equal
- Eq
+ /// Equal
+ Eq
- /// Greater than
- Gt
-}
+ /// Greater than
+ Gt
+ }
-/// Inverts an order, so less-than becomes greater-than and greater-than
-/// becomes less-than.
-///
-/// ## Examples
-///
-/// > reverse(Lt)
-/// Gt
-///
-/// > reverse(Eq)
-/// Eq
-///
-/// > reverse(Lt)
-/// Gt
-///
-pub fn reverse(order: Order) -> Order {
- case order {
- Lt -> Gt
- Eq -> Eq
- Gt -> Lt
+ /// Inverts an order, so less-than becomes greater-than and greater-than
+ /// becomes less-than.
+ ///
+ /// ## Examples
+ ///
+ /// > reverse(Lt)
+ /// Gt
+ ///
+ /// > reverse(Eq)
+ /// Eq
+ ///
+ /// > reverse(Lt)
+ /// Gt
+ ///
+ pub fn reverse(order: Order) -> Order {
+ case order {
+ Lt -> Gt
+ Eq -> Eq
+ Gt -> Lt
+ }
}
-}
-/// Produces a numeric representation of the order.
-///
-/// ## Examples
-///
-/// > to_int(Lt)
-/// -1
-///
-/// > to_int(Eq)
-/// 0
-///
-/// > to_int(Gt)
-/// 1
-///
-pub fn to_int(order: Order) -> Int {
- case order {
- Lt -> -1
- Eq -> 0
- Gt -> 1
+ /// Produces a numeric representation of the order.
+ ///
+ /// ## Examples
+ ///
+ /// > to_int(Lt)
+ /// -1
+ ///
+ /// > to_int(Eq)
+ /// 0
+ ///
+ /// > to_int(Gt)
+ /// 1
+ ///
+ pub fn to_int(order: Order) -> Int {
+ case order {
+ Lt -> -1
+ Eq -> 0
+ Gt -> 1
+ }
}
-}
-/// Compares two Order values to one another, producing a new Order.
-///
-/// ## Examples
-///
-/// > compare(Eq, with: Lt)
-/// Gt
-///
-pub fn compare(a: Order, with b: Order) -> Order {
- case a, b {
- x, y if x == y -> Eq
- Lt, _ | Eq, Gt -> Lt
- _, _ -> Gt
+ /// Compares two Order values to one another, producing a new Order.
+ ///
+ /// ## Examples
+ ///
+ /// > compare(Eq, with: Lt)
+ /// Gt
+ ///
+ pub fn compare(a: Order, with b: Order) -> Order {
+ case a, b {
+ x, y if x == y -> Eq
+ Lt, _ | Eq, Gt -> Lt
+ _, _ -> Gt
+ }
}
-}
-/// Returns the largest of two orders.
-///
-/// ## Examples
-///
-/// > max(Eq, Lt)
-/// Eq
-///
-pub fn max(a: Order, b: Order) -> Order {
- case a, b {
- Gt, _ -> Gt
- Eq, Lt -> Eq
- _, _ -> b
+ /// Returns the largest of two orders.
+ ///
+ /// ## Examples
+ ///
+ /// > max(Eq, Lt)
+ /// Eq
+ ///
+ pub fn max(a: Order, b: Order) -> Order {
+ case a, b {
+ Gt, _ -> Gt
+ Eq, Lt -> Eq
+ _, _ -> b
+ }
}
-}
-/// Returns the smallest of two orders.
-///
-/// ## Examples
-///
-/// > min(Eq, Lt)
-/// Lt
-///
-pub fn min(a: Order, b: Order) -> Order {
- case a, b {
- Lt, _ -> Lt
- Eq, Gt -> Eq
- _, _ -> b
+ /// Returns the smallest of two orders.
+ ///
+ /// ## Examples
+ ///
+ /// > min(Eq, Lt)
+ /// Lt
+ ///
+ pub fn min(a: Order, b: Order) -> Order {
+ case a, b {
+ Lt, _ -> Lt
+ Eq, Gt -> Eq
+ _, _ -> b
+ }
}
}
diff --git a/src/gleam/os.gleam b/src/gleam/os.gleam
index fcaf724..af67e35 100644
--- a/src/gleam/os.gleam
+++ b/src/gleam/os.gleam
@@ -1,66 +1,69 @@
//// Function to interact with the host operating system.
-import gleam/list
-import gleam/map.{Map}
-import gleam/string
+if erlang {
+ import gleam/list
+ import gleam/map.{Map}
+ import gleam/string
-// Internal type for erlang interop.
-external type CharList
+ // Internal type for erlang interop.
+ external type CharList
-external fn os_getenv() -> List(CharList) =
- "os" "getenv"
+ external fn os_getenv() -> List(CharList) =
+ "os" "getenv"
-external fn os_putenv(key: CharList, value: CharList) -> Bool =
- "os" "putenv"
+ external fn os_putenv(key: CharList, value: CharList) -> Bool =
+ "os" "putenv"
-external fn os_unsetenv(key: CharList) -> Bool =
- "os" "unsetenv"
+ external fn os_unsetenv(key: CharList) -> Bool =
+ "os" "unsetenv"
-external fn char_list_to_string(CharList) -> String =
- "unicode" "characters_to_binary"
+ external fn char_list_to_string(CharList) -> String =
+ "unicode" "characters_to_binary"
-external fn string_to_char_list(String) -> CharList =
- "unicode" "characters_to_list"
+ external fn string_to_char_list(String) -> CharList =
+ "unicode" "characters_to_list"
-/// Returns all environment variables set on the system.
-pub fn get_env() -> Map(String, String) {
- list.map(
- os_getenv(),
- fn(char_list) {
- assert Ok(value) = string.split_once(char_list_to_string(char_list), "=")
- value
- },
- )
- |> map.from_list()
-}
+ /// Returns all environment variables set on the system.
+ pub fn get_env() -> Map(String, String) {
+ list.map(
+ os_getenv(),
+ fn(char_list) {
+ assert Ok(value) =
+ string.split_once(char_list_to_string(char_list), "=")
+ value
+ },
+ )
+ |> map.from_list()
+ }
-/// Sets an environment variable.
-pub fn insert_env(key: String, value: String) -> Nil {
- os_putenv(string_to_char_list(key), string_to_char_list(value))
- Nil
-}
+ /// Sets an environment variable.
+ pub fn insert_env(key: String, value: String) -> Nil {
+ os_putenv(string_to_char_list(key), string_to_char_list(value))
+ Nil
+ }
-/// Deletes an environment variable.
-pub fn delete_env(key: String) -> Nil {
- os_unsetenv(string_to_char_list(key))
- Nil
-}
+ /// Deletes an environment variable.
+ pub fn delete_env(key: String) -> Nil {
+ os_unsetenv(string_to_char_list(key))
+ Nil
+ }
-pub type TimeUnit {
- Second
- Millisecond
- Microsecond
- Nanosecond
-}
+ pub type TimeUnit {
+ Second
+ Millisecond
+ Microsecond
+ Nanosecond
+ }
-/// Returns the current OS system time.
-///
-/// https://erlang.org/doc/apps/erts/time_correction.html#OS_System_Time
-pub external fn system_time(TimeUnit) -> Int =
- "os" "system_time"
+ /// Returns the current OS system time.
+ ///
+ /// https://erlang.org/doc/apps/erts/time_correction.html#OS_System_Time
+ pub external fn system_time(TimeUnit) -> Int =
+ "os" "system_time"
-/// Returns the current OS system time as a tuple of Ints
-///
-/// http://erlang.org/doc/man/os.html#timestamp-0
-pub external fn erlang_timestamp() -> #(Int, Int, Int) =
- "os" "timestamp"
+ /// Returns the current OS system time as a tuple of Ints
+ ///
+ /// http://erlang.org/doc/man/os.html#timestamp-0
+ pub external fn erlang_timestamp() -> #(Int, Int, Int) =
+ "os" "timestamp"
+}
diff --git a/src/gleam/pair.gleam b/src/gleam/pair.gleam
index 6143ee9..246ce8c 100644
--- a/src/gleam/pair.gleam
+++ b/src/gleam/pair.gleam
@@ -1,61 +1,63 @@
-/// Returns the first element in a pair.
-///
-/// ## Examples
-///
-/// > first(#(1, 2))
-/// 1
-///
-pub fn first(pair: #(a, b)) -> a {
- let #(a, _) = pair
- a
-}
+if erlang {
+ /// Returns the first element in a pair.
+ ///
+ /// ## Examples
+ ///
+ /// > first(#(1, 2))
+ /// 1
+ ///
+ pub fn first(pair: #(a, b)) -> a {
+ let #(a, _) = pair
+ a
+ }
-/// Returns the second element in a pair.
-///
-/// ## Examples
-///
-/// > second(#(1, 2))
-/// 2
-///
-pub fn second(pair: #(a, b)) -> b {
- let #(_, a) = pair
- a
-}
+ /// Returns the second element in a pair.
+ ///
+ /// ## Examples
+ ///
+ /// > second(#(1, 2))
+ /// 2
+ ///
+ pub fn second(pair: #(a, b)) -> b {
+ let #(_, a) = pair
+ a
+ }
-/// Returns a new pair with the elements swapped.
-///
-/// ## Examples
-///
-/// > swap(#(1, 2))
-/// #(2, 1)
-///
-pub fn swap(pair: #(a, b)) -> #(b, a) {
- let #(a, b) = pair
- #(b, a)
-}
+ /// Returns a new pair with the elements swapped.
+ ///
+ /// ## Examples
+ ///
+ /// > swap(#(1, 2))
+ /// #(2, 1)
+ ///
+ pub fn swap(pair: #(a, b)) -> #(b, a) {
+ let #(a, b) = pair
+ #(b, a)
+ }
-/// Returns a new pair with the first element having had `with` applied to
-/// it.
-///
-/// ## Examples
-///
-/// > #(1, 2) |> map_first(fn(n) { n * 2 })
-/// 2
-///
-pub fn map_first(of pair: #(a, b), with fun: fn(a) -> c) -> #(c, b) {
- let #(a, b) = pair
- #(fun(a), b)
-}
+ /// Returns a new pair with the first element having had `with` applied to
+ /// it.
+ ///
+ /// ## Examples
+ ///
+ /// > #(1, 2) |> map_first(fn(n) { n * 2 })
+ /// 2
+ ///
+ pub fn map_first(of pair: #(a, b), with fun: fn(a) -> c) -> #(c, b) {
+ let #(a, b) = pair
+ #(fun(a), b)
+ }
-/// Returns a new pair with the second element having had `with` applied to
-/// it.
-///
-/// ## Examples
-///
-/// > #(1, 2) |> map_second(fn(n) { n * 2 })
-/// 4
-///
-pub fn map_second(of pair: #(a, b), with fun: fn(b) -> c) -> #(a, c) {
- let #(a, b) = pair
- #(a, fun(b))
+ /// Returns a new pair with the second element having had `with` applied to
+ /// it.
+ ///
+ /// ## Examples
+ ///
+ /// > #(1, 2) |> map_second(fn(n) { n * 2 })
+ /// 4
+ ///
+ pub fn map_second(of pair: #(a, b), with fun: fn(b) -> c) -> #(a, c) {
+ let #(a, b) = pair
+ #(a, fun(b))
+ }
}
diff --git a/src/gleam/queue.gleam b/src/gleam/queue.gleam
index 6b12cfb..80cea16 100644
--- a/src/gleam/queue.gleam
+++ b/src/gleam/queue.gleam
@@ -1,254 +1,258 @@
-import gleam/list
+if erlang {
+ import gleam/list
-/// A queue is an order collection of elements. It is similar to a list, but
-/// unlike a list elements can be added to or removed from either the front or
-/// the back in a performant fashion.
-///
-/// The internal representation may be different for two queues with the same
-/// elements in the same order if the queues were constructed in different
-/// ways. This is the price paid for a queue's fast access at both the front
-/// and the back.
-///
-/// Because of unpredictable internal representation the equality operator `==`
-/// may return surprising results, and the `is_equal` and `is_logically_equal`
-/// functions are the recommended way to test queues for equality.
-///
-pub opaque type Queue(element) {
- Queue(in: List(element), out: List(element))
-}
+ /// A queue is an order collection of elements. It is similar to a list, but
+ /// unlike a list elements can be added to or removed from either the front or
+ /// the back in a performant fashion.
+ ///
+ /// The internal representation may be different for two queues with the same
+ /// elements in the same order if the queues were constructed in different
+ /// ways. This is the price paid for a queue's fast access at both the front
+ /// and the back.
+ ///
+ /// Because of unpredictable internal representation the equality operator `==`
+ /// may return surprising results, and the `is_equal` and `is_logically_equal`
+ /// functions are the recommended way to test queues for equality.
+ ///
+ pub opaque type Queue(element) {
+ Queue(in: List(element), out: List(element))
+ }
-/// Creates a fresh queue that contains no values.
-///
-pub fn new() -> Queue(a) {
- Queue(in: [], out: [])
-}
+ /// Creates a fresh queue that contains no values.
+ ///
+ pub fn new() -> Queue(a) {
+ Queue(in: [], out: [])
+ }
-/// Converts a list of elements into a queue of the same elements in the same
-/// order. The head element in the list becomes the front element in the queue.
-///
-/// This function runs in constant time.
-///
-/// # Examples
-///
-/// > [1, 2, 3] |> from_list |> length
-/// 3
-///
-pub fn from_list(list: List(a)) -> Queue(a) {
- Queue(in: [], out: list)
-}
+ /// Converts a list of elements into a queue of the same elements in the same
+ /// order. The head element in the list becomes the front element in the queue.
+ ///
+ /// This function runs in constant time.
+ ///
+ /// # Examples
+ ///
+ /// > [1, 2, 3] |> from_list |> length
+ /// 3
+ ///
+ pub fn from_list(list: List(a)) -> Queue(a) {
+ Queue(in: [], out: list)
+ }
-/// Converts a queue of elements into a list of the same elements in the same
-/// order. The front element in the queue becomes the head element in the list.
-///
-/// This function runs in linear time.
-///
-/// # Examples
-///
-/// > new() |> push_back(1) |> push_back(2) |> to_list
-/// [1, 2]
-///
-pub fn to_list(queue: Queue(a)) -> List(a) {
- queue.out
- |> list.append(list.reverse(queue.in))
-}
+ /// Converts a queue of elements into a list of the same elements in the same
+ /// order. The front element in the queue becomes the head element in the list.
+ ///
+ /// This function runs in linear time.
+ ///
+ /// # Examples
+ ///
+ /// > new() |> push_back(1) |> push_back(2) |> to_list
+ /// [1, 2]
+ ///
+ pub fn to_list(queue: Queue(a)) -> List(a) {
+ queue.out
+ |> list.append(list.reverse(queue.in))
+ }
-/// Determines whether or not the queue is empty.
-///
-/// This function runs in constant time.
-///
-/// ## Examples
-///
-/// > [] |> from_list |> is_empty
-/// True
-///
-/// > [1] |> from_list |> is_empty
-/// False
-///
-/// > [1, 2] |> from_list |> is_empty
-/// False
-///
-pub fn is_empty(queue: Queue(a)) -> Bool {
- queue.in == [] && queue.out == []
-}
+ /// Determines whether or not the queue is empty.
+ ///
+ /// This function runs in constant time.
+ ///
+ /// ## Examples
+ ///
+ /// > [] |> from_list |> is_empty
+ /// True
+ ///
+ /// > [1] |> from_list |> is_empty
+ /// False
+ ///
+ /// > [1, 2] |> from_list |> is_empty
+ /// False
+ ///
+ pub fn is_empty(queue: Queue(a)) -> Bool {
+ queue.in == [] && queue.out == []
+ }
-/// Counts the number of elements in a given queue.
-///
-/// This function has to traverse the queue to determine the number of elements,
-/// so it runs in linear time.
-///
-/// ## Examples
-///
-/// > length(from_list([]))
-/// 0
-///
-/// > length(from_list([1]))
-/// 1
-///
-/// > length(from_list([1, 2]))
-/// 2
-///
-pub fn length(queue: Queue(a)) -> Int {
- list.length(queue.in) + list.length(queue.out)
-}
+ /// Counts the number of elements in a given queue.
+ ///
+ /// This function has to traverse the queue to determine the number of elements,
+ /// so it runs in linear time.
+ ///
+ /// ## Examples
+ ///
+ /// > length(from_list([]))
+ /// 0
+ ///
+ /// > length(from_list([1]))
+ /// 1
+ ///
+ /// > length(from_list([1, 2]))
+ /// 2
+ ///
+ pub fn length(queue: Queue(a)) -> Int {
+ list.length(queue.in) + list.length(queue.out)
+ }
-/// Pushes an element onto the back of the queue.
-///
-/// # Examples
-///
-/// > [1, 2] |> from_list |> push_back(3) |> to_list
-/// [1, 2, 3]
-///
-pub fn push_back(onto queue: Queue(a), this item: a) -> Queue(a) {
- Queue(in: [item, ..queue.in], out: queue.out)
-}
+ /// Pushes an element onto the back of the queue.
+ ///
+ /// # Examples
+ ///
+ /// > [1, 2] |> from_list |> push_back(3) |> to_list
+ /// [1, 2, 3]
+ ///
+ pub fn push_back(onto queue: Queue(a), this item: a) -> Queue(a) {
+ Queue(in: [item, ..queue.in], out: queue.out)
+ }
-/// Pushes an element onto the front of the queue.
-///
-/// # Examples
-///
-/// > [0, 0] |> from_list |> push_front(1) |> to_list
-/// [1, 0, 0]
-///
-pub fn push_front(onto queue: Queue(a), this item: a) -> Queue(a) {
- Queue(in: queue.in, out: [item, ..queue.out])
-}
+ /// Pushes an element onto the front of the queue.
+ ///
+ /// # Examples
+ ///
+ /// > [0, 0] |> from_list |> push_front(1) |> to_list
+ /// [1, 0, 0]
+ ///
+ pub fn push_front(onto queue: Queue(a), this item: a) -> Queue(a) {
+ Queue(in: queue.in, out: [item, ..queue.out])
+ }
-/// Gets the last element from the queue, returning the
-/// element and a new queue without that element.
-///
-/// This function typically runs in constant time, but will occasionally run in
-/// linear time.
-///
-/// # Examples
-///
-/// > queue.new()
-/// > |> queue.push_back(0)
-/// > |> queue.push_back(1)
-/// > |> queue.pop_back()
-/// Ok(#(1, queue.push_front(queue.new(), 0)))
-///
-/// > queue.new()
-/// > |> queue.push_front(0)
-/// > |> queue.pop_back()
-/// Ok(#(0, queue.new()))
-///
-/// > queue.new()
-/// > |> queue.pop_back()
-/// Error(Nil)
-///
-pub fn pop_back(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) {
- case queue {
- Queue(in: [], out: []) -> Error(Nil)
- Queue(in: [], out: out) -> pop_back(Queue(in: list.reverse(out), out: []))
- Queue(in: [first, ..rest], out: out) -> {
- let queue = Queue(in: rest, out: out)
- Ok(#(first, queue))
+ /// Gets the last element from the queue, returning the
+ /// element and a new queue without that element.
+ ///
+ /// This function typically runs in constant time, but will occasionally run in
+ /// linear time.
+ ///
+ /// # Examples
+ ///
+ /// > queue.new()
+ /// > |> queue.push_back(0)
+ /// > |> queue.push_back(1)
+ /// > |> queue.pop_back()
+ /// Ok(#(1, queue.push_front(queue.new(), 0)))
+ ///
+ /// > queue.new()
+ /// > |> queue.push_front(0)
+ /// > |> queue.pop_back()
+ /// Ok(#(0, queue.new()))
+ ///
+ /// > queue.new()
+ /// > |> queue.pop_back()
+ /// Error(Nil)
+ ///
+ pub fn pop_back(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) {
+ case queue {
+ Queue(in: [], out: []) -> Error(Nil)
+ Queue(in: [], out: out) -> pop_back(Queue(in: list.reverse(out), out: []))
+ Queue(in: [first, ..rest], out: out) -> {
+ let queue = Queue(in: rest, out: out)
+ Ok(#(first, queue))
+ }
}
}
-}
-/// Gets the first element from the queue, returning the
-/// element and a new queue without that element.
-///
-/// This function typically runs in constant time, but will occasionally run in
-/// linear time.
-///
-/// # Examples
-///
-/// > queue.new()
-/// > |> queue.push_front(1)
-/// > |> queue.push_front(0)
-/// > |> queue.pop_front()
-/// Ok(#(0, queue.push_back(queue.new(), 1)))
-///
-/// > queue.new()
-/// > |> queue.push_back(0)
-/// > |> queue.pop_front()
-/// Ok(#(0, queue.new()))
-///
-/// > queue.new()
-/// > |> queue.pop_back()
-/// Error(Nil)
-///
-pub fn pop_front(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) {
- case queue {
- Queue(in: [], out: []) -> Error(Nil)
- Queue(in: in, out: []) -> pop_front(Queue(in: [], out: list.reverse(in)))
- Queue(in: in, out: [first, ..rest]) -> {
- let queue = Queue(in: in, out: rest)
- Ok(#(first, queue))
+ /// Gets the first element from the queue, returning the
+ /// element and a new queue without that element.
+ ///
+ /// This function typically runs in constant time, but will occasionally run in
+ /// linear time.
+ ///
+ /// # Examples
+ ///
+ /// > queue.new()
+ /// > |> queue.push_front(1)
+ /// > |> queue.push_front(0)
+ /// > |> queue.pop_front()
+ /// Ok(#(0, queue.push_back(queue.new(), 1)))
+ ///
+ /// > queue.new()
+ /// > |> queue.push_back(0)
+ /// > |> queue.pop_front()
+ /// Ok(#(0, queue.new()))
+ ///
+ /// > queue.new()
+ /// > |> queue.pop_back()
+ /// Error(Nil)
+ ///
+ pub fn pop_front(from queue: Queue(a)) -> Result(#(a, Queue(a)), Nil) {
+ case queue {
+ Queue(in: [], out: []) -> Error(Nil)
+ Queue(in: in, out: []) -> pop_front(Queue(in: [], out: list.reverse(in)))
+ Queue(in: in, out: [first, ..rest]) -> {
+ let queue = Queue(in: in, out: rest)
+ Ok(#(first, queue))
+ }
}
}
-}
-/// Creates a new queue from a given queue containing the same elements, but in
-/// the opposite order.
-///
-/// This function runs in constant time.
-///
-/// ## Examples
-///
-/// > reverse(from_list([]))
-/// []
-///
-/// > reverse(from_list([1]))
-/// [1]
-///
-/// > reverse(from_list([1, 2]))
-/// [2, 1]
-///
-pub fn reverse(queue: Queue(a)) -> Queue(a) {
- Queue(in: queue.out, out: queue.in)
-}
+ /// Creates a new queue from a given queue containing the same elements, but in
+ /// the opposite order.
+ ///
+ /// This function runs in constant time.
+ ///
+ /// ## Examples
+ ///
+ /// > reverse(from_list([]))
+ /// []
+ ///
+ /// > reverse(from_list([1]))
+ /// [1]
+ ///
+ /// > reverse(from_list([1, 2]))
+ /// [2, 1]
+ ///
+ pub fn reverse(queue: Queue(a)) -> Queue(a) {
+ Queue(in: queue.out, out: queue.in)
+ }
-fn check_equal(
- xs: List(t),
- x_tail: List(t),
- ys: List(t),
- y_tail: List(t),
- eq: fn(t, t) -> Bool,
-) -> Bool {
- case xs, x_tail, ys, y_tail {
- [], [], [], [] -> True
- [x, ..xs], _, [y, ..ys], _ ->
- case eq(x, y) {
- False -> False
- True -> check_equal(xs, x_tail, ys, y_tail, eq)
- }
- [], [_, .._], _, _ -> check_equal(list.reverse(x_tail), [], ys, y_tail, eq)
- _, _, [], [_, .._] -> check_equal(xs, x_tail, list.reverse(y_tail), [], eq)
- _, _, _, _ -> False
+ fn check_equal(
+ xs: List(t),
+ x_tail: List(t),
+ ys: List(t),
+ y_tail: List(t),
+ eq: fn(t, t) -> Bool,
+ ) -> Bool {
+ case xs, x_tail, ys, y_tail {
+ [], [], [], [] -> True
+ [x, ..xs], _, [y, ..ys], _ ->
+ case eq(x, y) {
+ False -> False
+ True -> check_equal(xs, x_tail, ys, y_tail, eq)
+ }
+ [], [_, .._], _, _ ->
+ check_equal(list.reverse(x_tail), [], ys, y_tail, eq)
+ _, _, [], [_, .._] ->
+ check_equal(xs, x_tail, list.reverse(y_tail), [], eq)
+ _, _, _, _ -> False
+ }
}
-}
-/// Checks whether two queues have equal elements in the same order, where the
-/// equality of elements is determined by a given equality checking function.
-///
-/// This function is useful as the internal representation may be different for
-/// two queues with the same elements in the same order depending on how they
-/// were constructed, so the equality operator `==` may return surprising
-/// results.
-///
-/// This function runs in linear time multiplied by the time taken by the
-/// element equality checking function.
-///
-pub fn is_logically_equal(
- a: Queue(t),
- to b: Queue(t),
- checking element_is_equal: fn(t, t) -> Bool,
-) -> Bool {
- check_equal(a.out, a.in, b.out, b.in, element_is_equal)
-}
+ /// Checks whether two queues have equal elements in the same order, where the
+ /// equality of elements is determined by a given equality checking function.
+ ///
+ /// This function is useful as the internal representation may be different for
+ /// two queues with the same elements in the same order depending on how they
+ /// were constructed, so the equality operator `==` may return surprising
+ /// results.
+ ///
+ /// This function runs in linear time multiplied by the time taken by the
+ /// element equality checking function.
+ ///
+ pub fn is_logically_equal(
+ a: Queue(t),
+ to b: Queue(t),
+ checking element_is_equal: fn(t, t) -> Bool,
+ ) -> Bool {
+ check_equal(a.out, a.in, b.out, b.in, element_is_equal)
+ }
-/// Checks whether two queues have the same elements in the same order.
-///
-/// This function is useful as the internal representation may be different for
-/// two queues with the same elements in the same order depending on how they
-/// were constructed, so the equality operator `==` may return surprising
-/// results.
-///
-/// This function runs in linear time.
-///
-pub fn is_equal(a: Queue(t), to b: Queue(t)) -> Bool {
- check_equal(a.out, a.in, b.out, b.in, fn(a, b) { a == b })
+ /// Checks whether two queues have the same elements in the same order.
+ ///
+ /// This function is useful as the internal representation may be different for
+ /// two queues with the same elements in the same order depending on how they
+ /// were constructed, so the equality operator `==` may return surprising
+ /// results.
+ ///
+ /// This function runs in linear time.
+ ///
+ pub fn is_equal(a: Queue(t), to b: Queue(t)) -> Bool {
+ check_equal(a.out, a.in, b.out, b.in, fn(a, b) { a == b })
+ }
}
diff --git a/src/gleam/regex.gleam b/src/gleam/regex.gleam
index 07aa1ba..87f06c8 100644
--- a/src/gleam/regex.gleam
+++ b/src/gleam/regex.gleam
@@ -3,121 +3,123 @@
//// all of the PCRE library is interfaced and some parts of the library go beyond
//// what PCRE offers. Currently PCRE version 8.40 (release date 2017-01-11) is used.
-import gleam/option.{Option}
+if erlang {
+ import gleam/option.{Option}
-pub external type Regex
+ pub external type Regex
-/// The details about a particular match:
-///
-pub type Match {
- Match(
- /// The full string of the match.
- content: String,
- /// The byte index of the match in the original string.
- byte_index: Int,
- /// A Regex can have subpatterns, sup-parts that are in parentheses.
- submatches: List(Option(String)),
- )
-}
+ /// The details about a particular match:
+ ///
+ pub type Match {
+ Match(
+ /// The full string of the match.
+ content: String,
+ /// The byte index of the match in the original string.
+ byte_index: Int,
+ /// A Regex can have subpatterns, sup-parts that are in parentheses.
+ submatches: List(Option(String)),
+ )
+ }
-/// When a regular expression fails to compile:
-///
-pub type CompileError {
- CompileError(
- /// The problem encountered that caused the compilation to fail
- error: String,
- /// The byte index into the string to where the problem was found
- byte_index: Int,
- )
-}
+ /// When a regular expression fails to compile:
+ ///
+ pub type CompileError {
+ CompileError(
+ /// The problem encountered that caused the compilation to fail
+ error: String,
+ /// The byte index into the string to where the problem was found
+ byte_index: Int,
+ )
+ }
-pub type Options {
- Options(case_insensitive: Bool, multi_line: Bool)
-}
+ pub type Options {
+ Options(case_insensitive: Bool, multi_line: Bool)
+ }
-/// Creates a Regex with some additional options.
-///
-/// ## Examples
-///
-/// > let options = Options(case_insensitive: False, multi_line: True)
-/// > assert Ok(re) = compile("^[0-9]", with: options)
-/// > match(re, "abc\n123")
-/// True
-///
-/// > let options = Options(case_insensitive: True, multi_line: False)
-/// > assert Ok(re) = compile("[A-Z]", with: options)
-/// > match(re, "abc123")
-/// True
-///
-pub external fn compile(String, with: Options) -> Result(Regex, CompileError) =
- "gleam_stdlib" "compile_regex"
+ /// Creates a Regex with some additional options.
+ ///
+ /// ## Examples
+ ///
+ /// > let options = Options(case_insensitive: False, multi_line: True)
+ /// > assert Ok(re) = compile("^[0-9]", with: options)
+ /// > match(re, "abc\n123")
+ /// True
+ ///
+ /// > let options = Options(case_insensitive: True, multi_line: False)
+ /// > assert Ok(re) = compile("[A-Z]", with: options)
+ /// > match(re, "abc123")
+ /// True
+ ///
+ pub external fn compile(String, with: Options) -> Result(Regex, CompileError) =
+ "gleam_stdlib" "compile_regex"
-/// Creates a new Regex.
-///
-/// ## Examples
-///
-/// > assert Ok(re) = from_string("[0-9]")
-/// > match(re, "abc123")
-/// True
-///
-/// > match(re, "abcxyz")
-/// False
-///
-/// > from_string("[0-9")
-/// Error(
-/// CompileError(
-/// error: "missing terminating ] for character class",
-/// byte_index: 4
-/// )
-/// )
-///
-pub fn from_string(pattern: String) -> Result(Regex, CompileError) {
- compile(pattern, Options(case_insensitive: False, multi_line: False))
-}
+ /// Creates a new Regex.
+ ///
+ /// ## Examples
+ ///
+ /// > assert Ok(re) = from_string("[0-9]")
+ /// > match(re, "abc123")
+ /// True
+ ///
+ /// > match(re, "abcxyz")
+ /// False
+ ///
+ /// > from_string("[0-9")
+ /// Error(
+ /// CompileError(
+ /// error: "missing terminating ] for character class",
+ /// byte_index: 4
+ /// )
+ /// )
+ ///
+ pub fn from_string(pattern: String) -> Result(Regex, CompileError) {
+ compile(pattern, Options(case_insensitive: False, multi_line: False))
+ }
-/// Returns a boolean indicating whether there was a match or not.
-///
-/// ## Examples
-///
-/// > assert Ok(re) = from_string("^f.o.?")
-/// > check(with: re, content: "foo")
-/// True
-///
-/// > check(with: re, content: "boo")
-/// False
-///
-pub external fn check(with: Regex, content: String) -> Bool =
- "gleam_stdlib" "regex_match"
+ /// Returns a boolean indicating whether there was a match or not.
+ ///
+ /// ## Examples
+ ///
+ /// > assert Ok(re) = from_string("^f.o.?")
+ /// > check(with: re, content: "foo")
+ /// True
+ ///
+ /// > check(with: re, content: "boo")
+ /// False
+ ///
+ pub external fn check(with: Regex, content: String) -> Bool =
+ "gleam_stdlib" "regex_match"
-/// Splits a string
-///
-/// ## Examples
-///
-/// > assert Ok(re) = from_string(" *, *")
-/// > split(with: re, content: "foo,32, 4, 9 ,0")
-/// ["foo", "32", "4", "9", "0"]
-///
-pub external fn split(with: Regex, content: String) -> List(String) =
- "gleam_stdlib" "regex_split"
+ /// Splits a string
+ ///
+ /// ## Examples
+ ///
+ /// > assert Ok(re) = from_string(" *, *")
+ /// > split(with: re, content: "foo,32, 4, 9 ,0")
+ /// ["foo", "32", "4", "9", "0"]
+ ///
+ pub external fn split(with: Regex, content: String) -> List(String) =
+ "gleam_stdlib" "regex_split"
-/// Collects all matches of the regular expression.
-///
-/// ## Examples
-///
-/// > assert Ok(re) = regex.from_string("[oi]n a (\\w+)")
-/// > regex.scan(with: re, content: "I am on a boat in a lake.")
-/// [
-/// Match(
-/// content: "on a boat",
-/// byte_index: 5,
-/// submatches: [Some("boat")]
-/// ),
-/// Match(
-/// content: "in a lake",
-/// byte_index: 15,
-/// submatches: [Some("lake")]
-/// )
-/// ]
-///
-pub external fn scan(with: Regex, content: String) -> List(Match) =
- "gleam_stdlib" "regex_scan"
+ /// Collects all matches of the regular expression.
+ ///
+ /// ## Examples
+ ///
+ /// > assert Ok(re) = regex.from_string("[oi]n a (\\w+)")
+ /// > regex.scan(with: re, content: "I am on a boat in a lake.")
+ /// [
+ /// Match(
+ /// content: "on a boat",
+ /// byte_index: 5,
+ /// submatches: [Some("boat")]
+ /// ),
+ /// Match(
+ /// content: "in a lake",
+ /// byte_index: 15,
+ /// submatches: [Some("lake")]
+ /// )
+ /// ]
+ ///
+ pub external fn scan(with: Regex, content: String) -> List(Match) =
+ "gleam_stdlib" "regex_scan"
+}
diff --git a/src/gleam/result.gleam b/src/gleam/result.gleam
index d0601bf..4527516 100644
--- a/src/gleam/result.gleam
+++ b/src/gleam/result.gleam
@@ -1,280 +1,282 @@
-import gleam/list
+if erlang {
+ import gleam/list
-/// Result represents the result of something that may succeed or not.
-/// `Ok` means it was successful, `Error` means it was not successful.
-///
-pub type Result(success, error) =
- Result(success, error)
+ /// Result represents the result of something that may succeed or not.
+ /// `Ok` means it was successful, `Error` means it was not successful.
+ ///
+ pub type Result(success, error) =
+ Result(success, error)
-/// Nil is a type used to represent the absence of something, similar to null
-/// or undefined in other languages.
-///
-/// Unlike some other languages values cannot be implicitly nil.
-///
-pub type Nil =
- Nil
+ /// Nil is a type used to represent the absence of something, similar to null
+ /// or undefined in other languages.
+ ///
+ /// Unlike some other languages values cannot be implicitly nil.
+ ///
+ pub type Nil =
+ Nil
-/// Checks whether the result is an Ok value.
-///
-/// ## Examples
-///
-/// > is_ok(Ok(1))
-/// True
-///
-/// > is_ok(Error(Nil))
-/// False
-///
-pub fn is_ok(result: Result(a, e)) -> Bool {
- case result {
- Error(_) -> False
- Ok(_) -> True
+ /// Checks whether the result is an Ok value.
+ ///
+ /// ## Examples
+ ///
+ /// > is_ok(Ok(1))
+ /// True
+ ///
+ /// > is_ok(Error(Nil))
+ /// False
+ ///
+ pub fn is_ok(result: Result(a, e)) -> Bool {
+ case result {
+ Error(_) -> False
+ Ok(_) -> True
+ }
}
-}
-/// Checks whether the result is an Error value.
-///
-/// ## Examples
-///
-/// > is_error(Ok(1))
-/// False
-///
-/// > is_error(Error(Nil))
-/// True
-///
-pub fn is_error(result: Result(a, e)) -> Bool {
- case result {
- Ok(_) -> False
- Error(_) -> True
+ /// Checks whether the result is an Error value.
+ ///
+ /// ## Examples
+ ///
+ /// > is_error(Ok(1))
+ /// False
+ ///
+ /// > is_error(Error(Nil))
+ /// True
+ ///
+ pub fn is_error(result: Result(a, e)) -> Bool {
+ case result {
+ Ok(_) -> False
+ Error(_) -> True
+ }
}
-}
-/// Updates a value held within the Ok of a result by calling a given function
-/// on it.
-///
-/// If the result is an Error rather than OK the function is not called and the
-/// result stays the same.
-///
-/// ## Examples
-///
-/// > map(over: Ok(1), with: fn(x) { x + 1 })
-/// Ok(2)
-///
-/// > map(over: Error(1), with: fn(x) { x + 1 })
-/// Error(1)
-///
-pub fn map(over result: Result(a, e), with fun: fn(a) -> b) -> Result(b, e) {
- case result {
- Ok(x) -> Ok(fun(x))
- Error(e) -> Error(e)
+ /// Updates a value held within the Ok of a result by calling a given function
+ /// on it.
+ ///
+ /// If the result is an Error rather than OK the function is not called and the
+ /// result stays the same.
+ ///
+ /// ## Examples
+ ///
+ /// > map(over: Ok(1), with: fn(x) { x + 1 })
+ /// Ok(2)
+ ///
+ /// > map(over: Error(1), with: fn(x) { x + 1 })
+ /// Error(1)
+ ///
+ pub fn map(over result: Result(a, e), with fun: fn(a) -> b) -> Result(b, e) {
+ case result {
+ Ok(x) -> Ok(fun(x))
+ Error(e) -> Error(e)
+ }
}
-}
-/// Updates a value held within the Error of a result by calling a given function
-/// on it.
-///
-/// If the result is Ok rather than Error the function is not called and the
-/// result stays the same.
-///
-/// ## Examples
-///
-/// > map_error(over: Error(1), with: fn(x) { x + 1 })
-/// Error(2)
-///
-/// > map_error(over: Ok(1), with: fn(x) { x + 1 })
-/// Ok(1)
-///
-pub fn map_error(
- over result: Result(a, e),
- with fun: fn(e) -> f,
-) -> Result(a, f) {
- case result {
- Ok(x) -> Ok(x)
- Error(error) -> Error(fun(error))
+ /// Updates a value held within the Error of a result by calling a given function
+ /// on it.
+ ///
+ /// If the result is Ok rather than Error the function is not called and the
+ /// result stays the same.
+ ///
+ /// ## Examples
+ ///
+ /// > map_error(over: Error(1), with: fn(x) { x + 1 })
+ /// Error(2)
+ ///
+ /// > map_error(over: Ok(1), with: fn(x) { x + 1 })
+ /// Ok(1)
+ ///
+ pub fn map_error(
+ over result: Result(a, e),
+ with fun: fn(e) -> f,
+ ) -> Result(a, f) {
+ case result {
+ Ok(x) -> Ok(x)
+ Error(error) -> Error(fun(error))
+ }
}
-}
-/// Merges a nested Result into a single layer.
-///
-/// ## Examples
-///
-/// > flatten(Ok(Ok(1)))
-/// Ok(1)
-///
-/// > flatten(Ok(Error(""))
-/// Error("")
-///
-/// > flatten(Error(Nil))
-/// Error(Nil)
-///
-pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) {
- case result {
- Ok(x) -> x
- Error(error) -> Error(error)
+ /// Merges a nested Result into a single layer.
+ ///
+ /// ## Examples
+ ///
+ /// > flatten(Ok(Ok(1)))
+ /// Ok(1)
+ ///
+ /// > flatten(Ok(Error(""))
+ /// Error("")
+ ///
+ /// > flatten(Error(Nil))
+ /// Error(Nil)
+ ///
+ pub fn flatten(result: Result(Result(a, e), e)) -> Result(a, e) {
+ case result {
+ Ok(x) -> x
+ Error(error) -> Error(error)
+ }
}
-}
-/// Updates a value held within the Ok of a result by calling a given function
-/// on it, where the given function also returns a result. The two results are
-/// then merged together into one result.
-///
-/// If the result is an Error rather than OK the function is not called and the
-/// result stays the same.
-///
-/// This function is the equivalent of calling `map` followed by `flatten`, and
-/// it is useful for chaining together multiple functions that may fail.
-///
-/// ## Examples
-///
-/// > then(Ok(1), fn(x) { Ok(x + 1) })
-/// Ok(2)
-///
-/// > then(Ok(1), fn(x) { Ok(#("a", x)) })
-/// Ok(#("a", 1))
-///
-/// > then(Ok(1), fn(x) { Error("Oh no") })
-/// Error("Oh no")
-///
-/// > then(Error(Nil), fn(x) { Ok(x + 1) })
-/// Error(Nil)
-///
-pub fn then(
- result: Result(a, e),
- apply fun: fn(a) -> Result(b, e),
-) -> Result(b, e) {
- case result {
- Ok(x) -> fun(x)
- Error(e) -> Error(e)
+ /// Updates a value held within the Ok of a result by calling a given function
+ /// on it, where the given function also returns a result. The two results are
+ /// then merged together into one result.
+ ///
+ /// If the result is an Error rather than OK the function is not called and the
+ /// result stays the same.
+ ///
+ /// This function is the equivalent of calling `map` followed by `flatten`, and
+ /// it is useful for chaining together multiple functions that may fail.
+ ///
+ /// ## Examples
+ ///
+ /// > then(Ok(1), fn(x) { Ok(x + 1) })
+ /// Ok(2)
+ ///
+ /// > then(Ok(1), fn(x) { Ok(#("a", x)) })
+ /// Ok(#("a", 1))
+ ///
+ /// > then(Ok(1), fn(x) { Error("Oh no") })
+ /// Error("Oh no")
+ ///
+ /// > then(Error(Nil), fn(x) { Ok(x + 1) })
+ /// Error(Nil)
+ ///
+ pub fn then(
+ result: Result(a, e),
+ apply fun: fn(a) -> Result(b, e),
+ ) -> Result(b, e) {
+ case result {
+ Ok(x) -> fun(x)
+ Error(e) -> Error(e)
+ }
}
-}
-/// Extracts the Ok value from a result, returning a default value if the result
-/// is an Error.
-///
-/// ## Examples
-///
-/// > unwrap(Ok(1), 0)
-/// 1
-///
-/// > unwrap(Error(""), 0)
-/// 0
-///
-pub fn unwrap(result: Result(a, e), or default: a) -> a {
- case result {
- Ok(v) -> v
- Error(_) -> default
+ /// Extracts the Ok value from a result, returning a default value if the result
+ /// is an Error.
+ ///
+ /// ## Examples
+ ///
+ /// > unwrap(Ok(1), 0)
+ /// 1
+ ///
+ /// > unwrap(Error(""), 0)
+ /// 0
+ ///
+ pub fn unwrap(result: Result(a, e), or default: a) -> a {
+ case result {
+ Ok(v) -> v
+ Error(_) -> default
+ }
}
-}
-/// Extracts the Ok value from a result, evaluating the default function if the result
-/// is an Error.
-///
-/// ## Examples
-///
-/// > lazy_unwrap(Ok(1), fn() { 0 })
-/// 1
-///
-/// > lazy_unwrap(Error(""), fn() { 0 })
-/// 0
-///
-pub fn lazy_unwrap(result: Result(a, e), or default: fn() -> a) -> a {
- case result {
- Ok(v) -> v
- Error(_) -> default()
+ /// Extracts the Ok value from a result, evaluating the default function if the result
+ /// is an Error.
+ ///
+ /// ## Examples
+ ///
+ /// > lazy_unwrap(Ok(1), fn() { 0 })
+ /// 1
+ ///
+ /// > lazy_unwrap(Error(""), fn() { 0 })
+ /// 0
+ ///
+ pub fn lazy_unwrap(result: Result(a, e), or default: fn() -> a) -> a {
+ case result {
+ Ok(v) -> v
+ Error(_) -> default()
+ }
}
-}
-/// Transforms any error into Error(Nil)
-///
-/// ## Examples
-///
-/// > nil_error(Error(1))
-/// Error(Nil)
-///
-/// > nil_error(Ok(1))
-/// Ok(1)
-///
-pub fn nil_error(result: Result(a, e)) -> Result(a, Nil) {
- map_error(result, fn(_) { Nil })
-}
+ /// Transforms any error into Error(Nil)
+ ///
+ /// ## Examples
+ ///
+ /// > nil_error(Error(1))
+ /// Error(Nil)
+ ///
+ /// > nil_error(Ok(1))
+ /// Ok(1)
+ ///
+ pub fn nil_error(result: Result(a, e)) -> Result(a, Nil) {
+ map_error(result, fn(_) { Nil })
+ }
-/// Returns the first value if it is Ok, otherwise return the second value.
-///
-/// ## Examples
-///
-/// > or(Ok(1), Ok(2))
-/// Ok(1)
-///
-/// > or(Ok(1), Error("Error 2"))
-/// Ok(1)
-///
-/// > or(Error("Error 1"), Ok(2))
-/// Ok(2)
-///
-/// > or(Error("Error 1"), Error("Error 2"))
-/// Error("Error 2")
-///
-pub fn or(first: Result(a, e), second: Result(a, e)) -> Result(a, e) {
- case first {
- Ok(_) -> first
- Error(_) -> second
+ /// Returns the first value if it is Ok, otherwise return the second value.
+ ///
+ /// ## Examples
+ ///
+ /// > or(Ok(1), Ok(2))
+ /// Ok(1)
+ ///
+ /// > or(Ok(1), Error("Error 2"))
+ /// Ok(1)
+ ///
+ /// > or(Error("Error 1"), Ok(2))
+ /// Ok(2)
+ ///
+ /// > or(Error("Error 1"), Error("Error 2"))
+ /// Error("Error 2")
+ ///
+ pub fn or(first: Result(a, e), second: Result(a, e)) -> Result(a, e) {
+ case first {
+ Ok(_) -> first
+ Error(_) -> second
+ }
}
-}
-/// Returns the first value if it is Ok, otherwise evaluates the given function for a fallback value.
-///
-/// ## Examples
-///
-/// > or(Ok(1), Ok(2))
-/// Ok(1)
-///
-/// > or(Ok(1), Error("Error 2"))
-/// Ok(1)
-///
-/// > or(Error("Error 1"), Ok(2))
-/// Ok(2)
-///
-/// > or(Error("Error 1"), Error("Error 2"))
-/// Error("Error 2")
-///
-pub fn lazy_or(
- first: Result(a, e),
- second: fn() -> Result(a, e),
-) -> Result(a, e) {
- case first {
- Ok(_) -> first
- Error(_) -> second()
+ /// Returns the first value if it is Ok, otherwise evaluates the given function for a fallback value.
+ ///
+ /// ## Examples
+ ///
+ /// > or(Ok(1), Ok(2))
+ /// Ok(1)
+ ///
+ /// > or(Ok(1), Error("Error 2"))
+ /// Ok(1)
+ ///
+ /// > or(Error("Error 1"), Ok(2))
+ /// Ok(2)
+ ///
+ /// > or(Error("Error 1"), Error("Error 2"))
+ /// Error("Error 2")
+ ///
+ pub fn lazy_or(
+ first: Result(a, e),
+ second: fn() -> Result(a, e),
+ ) -> Result(a, e) {
+ case first {
+ Ok(_) -> first
+ Error(_) -> second()
+ }
}
-}
-/// Combines a list of results into a single result.
-/// If all elements in the list are Ok then returns an Ok holding the list of values.
-/// If any element is Error then returns the first error.
-///
-/// ## Examples
-/// > all([Ok(1), Ok(2)])
-/// Ok([1, 2])
-///
-/// > all([Ok(1), Error("e")])
-/// Error("e")
-pub fn all(results: List(Result(a, e))) -> Result(List(a), e) {
- list.try_map(results, fn(x) { x })
-}
+ /// Combines a list of results into a single result.
+ /// If all elements in the list are Ok then returns an Ok holding the list of values.
+ /// If any element is Error then returns the first error.
+ ///
+ /// ## Examples
+ /// > all([Ok(1), Ok(2)])
+ /// Ok([1, 2])
+ ///
+ /// > all([Ok(1), Error("e")])
+ /// Error("e")
+ pub fn all(results: List(Result(a, e))) -> Result(List(a), e) {
+ list.try_map(results, fn(x) { x })
+ }
-pub fn replace_error(result: Result(a, e1), error: e2) -> Result(a, e2) {
- result
- |> map_error(fn(_) { error })
-}
+ pub fn replace_error(result: Result(a, e1), error: e2) -> Result(a, e2) {
+ result
+ |> map_error(fn(_) { error })
+ }
-/// Given a list of results
-/// Return only the values inside Ok
-///
-/// ## Examples
-///
-/// ```
-/// > values([Ok(1), None, Ok(3)])
-/// [1, 3]
-/// ```
-///
-pub fn values(results: List(Result(a, e))) -> List(a) {
- list.filter_map(results, fn(r) { r })
+ /// Given a list of results
+ /// Return only the values inside Ok
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > values([Ok(1), None, Ok(3)])
+ /// [1, 3]
+ /// ```
+ ///
+ pub fn values(results: List(Result(a, e))) -> List(a) {
+ list.filter_map(results, fn(r) { r })
+ }
}
diff --git a/src/gleam/set.gleam b/src/gleam/set.gleam
index 61bb47a..86c3ccb 100644
--- a/src/gleam/set.gleam
+++ b/src/gleam/set.gleam
@@ -1,207 +1,215 @@
-import gleam/map.{Map}
-import gleam/result
-import gleam/list
+if erlang {
+ import gleam/map.{Map}
+ import gleam/result
+ import gleam/list
-/// A set is a collection of unique members of the same type.
-///
-/// It is implemented using the `gleam/map` module, so inserts and lookups have
-/// logarithmic time complexity.
-///
-pub opaque type Set(member) {
- // A list is used as the map value as an empty list has the smallest
- // representation in Erlang's binary format
- Set(map: Map(member, List(Nil)))
-}
+ /// A set is a collection of unique members of the same type.
+ ///
+ /// It is implemented using the `gleam/map` module, so inserts and lookups have
+ /// logarithmic time complexity.
+ ///
+ pub opaque type Set(member) {
+ // A list is used as the map value as an empty list has the smallest
+ // representation in Erlang's binary format
+ Set(map: Map(member, List(Nil)))
+ }
-/// Creates a new empty set.
-///
-pub fn new() -> Set(member) {
- Set(map.new())
-}
+ /// Creates a new empty set.
+ ///
+ pub fn new() -> Set(member) {
+ Set(map.new())
+ }
-/// Gets the number of members in a set.
-///
-/// This function runs in constant time.
-///
-/// ## Examples
-///
-/// > new() |> insert(1) |> insert(2) |> size
-/// 2
-///
-pub fn size(set: Set(member)) -> Int {
- map.size(set.map)
-}
+ /// Gets the number of members in a set.
+ ///
+ /// This function runs in constant time.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert(1) |> insert(2) |> size
+ /// 2
+ ///
+ pub fn size(set: Set(member)) -> Int {
+ map.size(set.map)
+ }
-/// Inserts an member into the set.
-///
-/// This function runs in logarithmic time.
-///
-/// ## Examples
-///
-/// > new() |> insert(1) |> insert(2) |> size
-/// 2
-///
-pub fn insert(into set: Set(member), this member: member) -> Set(member) {
- Set(map: map.insert(set.map, member, []))
-}
+ /// Inserts an member into the set.
+ ///
+ /// This function runs in logarithmic time.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert(1) |> insert(2) |> size
+ /// 2
+ ///
+ pub fn insert(into set: Set(member), this member: member) -> Set(member) {
+ Set(map: map.insert(set.map, member, []))
+ }
-/// Checks whether a set contains a given member.
-///
-/// This function runs in logarithmic time.
-///
-/// ## Examples
-///
-/// > new() |> insert(2) |> contains(2)
-/// True
-///
-/// > new() |> insert(2) |> contains(1)
-/// False
-///
-pub fn contains(in set: Set(member), this member: member) -> Bool {
- set.map
- |> map.get(member)
- |> result.is_ok
-}
+ /// Checks whether a set contains a given member.
+ ///
+ /// This function runs in logarithmic time.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert(2) |> contains(2)
+ /// True
+ ///
+ /// > new() |> insert(2) |> contains(1)
+ /// False
+ ///
+ pub fn contains(in set: Set(member), this member: member) -> Bool {
+ set.map
+ |> map.get(member)
+ |> result.is_ok
+ }
-/// Removes an member from a set. If the set does not contain the member then
-/// the set is returned unchanged.
-///
-/// This function runs in logarithmic time.
-///
-/// ## Examples
-///
-/// > new() |> insert(2) |> delete(2) |> contains(1)
-/// False
-///
-pub fn delete(from set: Set(member), this member: member) -> Set(member) {
- Set(map: map.delete(set.map, member))
-}
+ /// Removes an member from a set. If the set does not contain the member then
+ /// the set is returned unchanged.
+ ///
+ /// This function runs in logarithmic time.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert(2) |> delete(2) |> contains(1)
+ /// False
+ ///
+ pub fn delete(from set: Set(member), this member: member) -> Set(member) {
+ Set(map: map.delete(set.map, member))
+ }
-/// Converts the set into a list of the contained members.
-///
-/// The list has no specific ordering, any unintentional ordering may change in
-/// future versions of Gleam or Erlang.
-///
-/// This function runs in linear time.
-///
-/// ## Examples
-///
-/// > new() |> insert(2) |> to_list
-/// [2]
-///
-pub fn to_list(set: Set(member)) -> List(member) {
- map.keys(set.map)
-}
+ /// Converts the set into a list of the contained members.
+ ///
+ /// The list has no specific ordering, any unintentional ordering may change in
+ /// future versions of Gleam or Erlang.
+ ///
+ /// This function runs in linear time.
+ ///
+ /// ## Examples
+ ///
+ /// > new() |> insert(2) |> to_list
+ /// [2]
+ ///
+ pub fn to_list(set: Set(member)) -> List(member) {
+ map.keys(set.map)
+ }
-/// Creates a new set of the members in a given list.
-///
-/// This function runs in loglinear time.
-///
-/// ## Examples
-///
-/// > import gleam/list
-/// > [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort
-/// [1, 3, 3, 4]
-///
-pub fn from_list(members: List(member)) -> Set(member) {
- let map =
- list.fold(
- over: members,
- from: map.new(),
- with: fn(k, m) { map.insert(m, k, []) },
- )
- Set(map)
-}
+ /// Creates a new set of the members in a given list.
+ ///
+ /// This function runs in loglinear time.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/list
+ /// > [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort
+ /// [1, 3, 3, 4]
+ ///
+ pub fn from_list(members: List(member)) -> Set(member) {
+ let map =
+ list.fold(
+ over: members,
+ from: map.new(),
+ with: fn(k, m) { map.insert(m, k, []) },
+ )
+ Set(map)
+ }
-/// Combines all entries into a single value by calling a given function on each
-/// one.
-///
-/// Sets are not ordered so the values are not returned in any specific order.
-/// Do not write code that relies on the order entries are used by this
-/// function as it may change in later versions of Gleam or Erlang.
-///
-/// # Examples
-///
-/// > from_list([1, 3, 9])
-/// > |> fold(0, fn(member, accumulator) { accumulator + member })
-/// 13
-///
-pub fn fold(
- over set: Set(member),
- from initial: acc,
- with reducer: fn(member, acc) -> acc,
-) -> acc {
- map.fold(over: set.map, from: initial, with: fn(k, _, a) { reducer(k, a) })
-}
+ /// Combines all entries into a single value by calling a given function on each
+ /// one.
+ ///
+ /// Sets are not ordered so the values are not returned in any specific order.
+ /// Do not write code that relies on the order entries are used by this
+ /// function as it may change in later versions of Gleam or Erlang.
+ ///
+ /// # Examples
+ ///
+ /// > from_list([1, 3, 9])
+ /// > |> fold(0, fn(member, accumulator) { accumulator + member })
+ /// 13
+ ///
+ pub fn fold(
+ over set: Set(member),
+ from initial: acc,
+ with reducer: fn(member, acc) -> acc,
+ ) -> acc {
+ map.fold(over: set.map, from: initial, with: fn(k, _, a) { reducer(k, a) })
+ }
-/// Creates a new set from an existing set, minus any members that a given
-/// function returns False for.
-///
-/// This function runs in loglinear time.
-///
-/// ## Examples
-///
-/// > import gleam/int
-/// > from_list([1, 4, 6, 3, 675, 44, 67])
-/// > |> filter(for: int.is_even)
-/// > |> to_list
-/// [4, 6, 44]
-///
-pub fn filter(
- in set: Set(member),
- for property: fn(member) -> Bool,
-) -> Set(member) {
- Set(map.filter(in: set.map, for: fn(m, _) { property(m) }))
-}
+ /// Creates a new set from an existing set, minus any members that a given
+ /// function returns False for.
+ ///
+ /// This function runs in loglinear time.
+ ///
+ /// ## Examples
+ ///
+ /// > import gleam/int
+ /// > from_list([1, 4, 6, 3, 675, 44, 67])
+ /// > |> filter(for: int.is_even)
+ /// > |> to_list
+ /// [4, 6, 44]
+ ///
+ pub fn filter(
+ in set: Set(member),
+ for property: fn(member) -> Bool,
+ ) -> Set(member) {
+ Set(map.filter(in: set.map, for: fn(m, _) { property(m) }))
+ }
-/// Creates a new map from a given map, only including any members which are in
-/// a given list.
-///
-/// This function runs in loglinear time.
-///
-/// ## Examples
-///
-/// > from_list([1, 2, 3]) |> take([1, 3, 5]) |> to_list
-/// [1, 3]
-///
-pub fn take(from set: Set(member), keeping desired: List(member)) -> Set(member) {
- Set(map.take(from: set.map, keeping: desired))
-}
+ /// Creates a new map from a given map, only including any members which are in
+ /// a given list.
+ ///
+ /// This function runs in loglinear time.
+ ///
+ /// ## Examples
+ ///
+ /// > from_list([1, 2, 3]) |> take([1, 3, 5]) |> to_list
+ /// [1, 3]
+ ///
+ pub fn take(
+ from set: Set(member),
+ keeping desired: List(member),
+ ) -> Set(member) {
+ Set(map.take(from: set.map, keeping: desired))
+ }
-fn order(first: Set(member), second: Set(member)) -> #(Set(member), Set(member)) {
- case map.size(first.map) > map.size(second.map) {
- True -> #(first, second)
- False -> #(second, first)
+ fn order(
+ first: Set(member),
+ second: Set(member),
+ ) -> #(Set(member), Set(member)) {
+ case map.size(first.map) > map.size(second.map) {
+ True -> #(first, second)
+ False -> #(second, first)
+ }
}
-}
-/// Creates a new set that contains all members of both given sets.
-///
-/// This function runs in loglinear time.
-///
-/// ## Examples
-///
-/// > union(from_list([1, 2]), from_list([2, 3])) |> to_list
-/// [1, 2, 3]
-///
-pub fn union(of first: Set(member), and second: Set(member)) -> Set(member) {
- let #(larger, smaller) = order(first, second)
- fold(over: smaller, from: larger, with: fn(m, a) { insert(a, m) })
-}
+ /// Creates a new set that contains all members of both given sets.
+ ///
+ /// This function runs in loglinear time.
+ ///
+ /// ## Examples
+ ///
+ /// > union(from_list([1, 2]), from_list([2, 3])) |> to_list
+ /// [1, 2, 3]
+ ///
+ pub fn union(of first: Set(member), and second: Set(member)) -> Set(member) {
+ let #(larger, smaller) = order(first, second)
+ fold(over: smaller, from: larger, with: fn(m, a) { insert(a, m) })
+ }
-/// Creates a new set that contains members that are present in both given sets.
-///
-/// This function runs in loglinear time.
-///
-/// ## Examples
-///
-/// > intersection(from_list([1, 2]), from_list([2, 3])) |> to_list
-/// [2]
-///
-pub fn intersection(
- of first: Set(member),
- and second: Set(member),
-) -> Set(member) {
- let #(larger, smaller) = order(first, second)
- take(from: larger, keeping: to_list(smaller))
+ /// Creates a new set that contains members that are present in both given sets.
+ ///
+ /// This function runs in loglinear time.
+ ///
+ /// ## Examples
+ ///
+ /// > intersection(from_list([1, 2]), from_list([2, 3])) |> to_list
+ /// [2]
+ ///
+ pub fn intersection(
+ of first: Set(member),
+ and second: Set(member),
+ ) -> Set(member) {
+ let #(larger, smaller) = order(first, second)
+ take(from: larger, keeping: to_list(smaller))
+ }
}
diff --git a/src/gleam/should.gleam b/src/gleam/should.gleam
index 0a4b04b..b7c739b 100644
--- a/src/gleam/should.gleam
+++ b/src/gleam/should.gleam
@@ -4,32 +4,54 @@
//// More information on running eunit can be found in [the rebar3
//// documentation](https://rebar3.org/docs/testing/eunit/).
-// TODO: Move this module into another package so it can be used as a
-// dep only in test.
-pub external type Expectation
+if erlang {
+ // TODO: Move this module into another package so it can be used as a
+ // dep only in test.
+ pub external fn equal(a, a) -> Nil =
+ "gleam_stdlib" "should_equal"
-pub external fn equal(a, a) -> Expectation =
- "gleam_stdlib" "should_equal"
+ pub external fn not_equal(a, a) -> Nil =
+ "gleam_stdlib" "should_not_equal"
-pub external fn not_equal(a, a) -> Expectation =
- "gleam_stdlib" "should_not_equal"
+ pub external fn be_ok(Result(a, b)) -> Nil =
+ "gleam_stdlib" "should_be_ok"
-pub fn be_true(actual: Bool) -> Expectation {
+ pub external fn be_error(Result(a, b)) -> Nil =
+ "gleam_stdlib" "should_be_error"
+}
+
+if javascript {
+ pub fn equal(a, b) {
+ assert True = a == b
+ Nil
+ }
+
+ pub fn not_equal(a, b) {
+ assert True = a != b
+ Nil
+ }
+
+ pub fn be_ok(a) {
+ assert Ok(_) = a
+ Nil
+ }
+
+ pub fn be_error(a) {
+ assert Error(_) = a
+ Nil
+ }
+}
+
+pub fn be_true(actual: Bool) -> Nil {
actual
|> equal(True)
}
-pub fn be_false(actual: Bool) -> Expectation {
+pub fn be_false(actual: Bool) -> Nil {
actual
|> equal(False)
}
-pub external fn be_ok(Result(a, b)) -> Expectation =
- "gleam_stdlib" "should_be_ok"
-
-pub external fn be_error(Result(a, b)) -> Expectation =
- "gleam_stdlib" "should_be_error"
-
-pub fn fail() -> Expectation {
+pub fn fail() -> Nil {
be_true(False)
}
diff --git a/src/gleam/string.gleam b/src/gleam/string.gleam
index ce7cd64..a4574dc 100644
--- a/src/gleam/string.gleam
+++ b/src/gleam/string.gleam
@@ -1,476 +1,482 @@
//// Strings in Gleam are UTF-8 binaries. They can be written in your code a
//// text surrounded by `"double quotes"`.
-import gleam/string_builder
-import gleam/dynamic.{Dynamic}
-import gleam/iterator
-import gleam/list
-import gleam/order
-import gleam/result
-
-pub type String =
- String
-
-/// A UtfCodepoint is the integer representation of a valid UTF codepoint
-pub type UtfCodepoint =
- UtfCodepoint
-
-/// Determines if a string is empty.
-///
-/// ## Examples
-///
-/// > is_empty("")
-/// True
-///
-/// > is_empty("the world")
-/// False
-///
-pub fn is_empty(str: String) -> Bool {
- str == ""
-}
+if erlang {
+ import gleam/string_builder
+ import gleam/dynamic.{Dynamic}
+ import gleam/iterator
+ import gleam/list
+ import gleam/order
+ import gleam/result
+
+ pub type String =
+ String
+
+ /// A UtfCodepoint is the integer representation of a valid UTF codepoint
+ pub type UtfCodepoint =
+ UtfCodepoint
+
+ /// Determines if a string is empty.
+ ///
+ /// ## Examples
+ ///
+ /// > is_empty("")
+ /// True
+ ///
+ /// > is_empty("the world")
+ /// False
+ ///
+ pub fn is_empty(str: String) -> Bool {
+ str == ""
+ }
-/// Gets the number of grapheme clusters in a given string.
-///
-/// This function has to iterate across the whole string to count the number of
-/// graphemes, so it runs in linear time.
-///
-/// ## Examples
-///
-/// > length("Gleam")
-/// 5
-///
-/// > length("ß↑e̊")
-/// 3
-///
-/// > length("")
-/// 0
-///
-pub external fn length(String) -> Int =
- "string" "length"
-
-///
-/// Reverses a string.
-///
-/// This function has to iterate across the whole string so it runs in linear
-/// time.
-///
-/// ## Examples
-///
-/// > reverse("stressed")
-/// "desserts"
-///
-pub fn reverse(string: String) -> String {
- string
- |> string_builder.from_string
- |> string_builder.reverse
- |> string_builder.to_string
-}
+ /// Gets the number of grapheme clusters in a given string.
+ ///
+ /// This function has to iterate across the whole string to count the number of
+ /// graphemes, so it runs in linear time.
+ ///
+ /// ## Examples
+ ///
+ /// > length("Gleam")
+ /// 5
+ ///
+ /// > length("ß↑e̊")
+ /// 3
+ ///
+ /// > length("")
+ /// 0
+ ///
+ pub external fn length(String) -> Int =
+ "string" "length"
+
+ ///
+ /// Reverses a string.
+ ///
+ /// This function has to iterate across the whole string so it runs in linear
+ /// time.
+ ///
+ /// ## Examples
+ ///
+ /// > reverse("stressed")
+ /// "desserts"
+ ///
+ pub fn reverse(string: String) -> String {
+ string
+ |> string_builder.from_string
+ |> string_builder.reverse
+ |> string_builder.to_string
+ }
-/// Creates a new string by replacing all occurrences of a given substring.
-///
-/// ## Examples
-///
-/// > replace("www.example.com", each: ".", with: "-")
-/// "www-example-com"
-///
-/// > replace("a,b,c,d,e", each: ",", with: "/")
-/// "a/b/c/d/e"
-///
-pub fn replace(
- in string: String,
- each pattern: String,
- with substitute: String,
-) -> String {
- string
- |> string_builder.from_string
- |> string_builder.replace(each: pattern, with: substitute)
- |> string_builder.to_string
-}
+ /// Creates a new string by replacing all occurrences of a given substring.
+ ///
+ /// ## Examples
+ ///
+ /// > replace("www.example.com", each: ".", with: "-")
+ /// "www-example-com"
+ ///
+ /// > replace("a,b,c,d,e", each: ",", with: "/")
+ /// "a/b/c/d/e"
+ ///
+ pub fn replace(
+ in string: String,
+ each pattern: String,
+ with substitute: String,
+ ) -> String {
+ string
+ |> string_builder.from_string
+ |> string_builder.replace(each: pattern, with: substitute)
+ |> string_builder.to_string
+ }
-/// Creates a new string with all the graphemes in the input string converted to
-/// lowercase.
-///
-/// Useful for case-insensitive comparisons.
-///
-/// ## Examples
-///
-/// > lowercase("X-FILES")
-/// "x-files"
-///
-pub external fn lowercase(String) -> String =
- "string" "lowercase"
-
-/// Creates a new string with all the graphemes in the input string converted to
-/// uppercase.
-///
-/// Useful for case-insensitive comparisons and VIRTUAL YELLING.
-///
-/// ## Examples
-///
-/// > uppercase("skinner")
-/// "SKINNER"
-///
-pub external fn uppercase(String) -> String =
- "string" "uppercase"
-
-/// Compares two strings to see which is "larger" by comparing their graphemes.
-///
-/// This does not compare the size or length of the given strings.
-///
-/// ## Examples
-///
-/// > compare("Anthony", "Anthony")
-/// order.Eq
-///
-/// > compare("A", "B")
-/// order.Lt
-///
-pub external fn compare(String, String) -> order.Order =
- "gleam_stdlib" "compare_strings"
-
-external fn erl_slice(String, Int, Int) -> String =
- "string" "slice"
-
-/// Takes a substring given a start and end Grapheme indexes. Negative indexes
-/// are taken starting from the *end* of the list.
-///
-/// ## Examples
-/// > slice(from: "gleam", at_index: 1, length: 2)
-/// "le"
-///
-/// > slice(from: "gleam", at_index: 1, length: 10)
-/// "leam"
-///
-/// > slice(from: "gleam", at_index: 10, length: 3)
-/// ""
-///
-/// > slice(from: "gleam", at_index: -2, length: 2)
-/// "am"
-///
-/// > slice(from: "gleam", at_index: -12, length: 2)
-/// ""
-///
-pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String {
- case len < 0 {
- True -> ""
- False ->
- case idx < 0 {
- True -> {
- let translated_idx = length(string) + idx
- case translated_idx < 0 {
- True -> ""
- False -> erl_slice(string, translated_idx, len)
+ /// Creates a new string with all the graphemes in the input string converted to
+ /// lowercase.
+ ///
+ /// Useful for case-insensitive comparisons.
+ ///
+ /// ## Examples
+ ///
+ /// > lowercase("X-FILES")
+ /// "x-files"
+ ///
+ pub external fn lowercase(String) -> String =
+ "string" "lowercase"
+
+ /// Creates a new string with all the graphemes in the input string converted to
+ /// uppercase.
+ ///
+ /// Useful for case-insensitive comparisons and VIRTUAL YELLING.
+ ///
+ /// ## Examples
+ ///
+ /// > uppercase("skinner")
+ /// "SKINNER"
+ ///
+ pub external fn uppercase(String) -> String =
+ "string" "uppercase"
+
+ /// Compares two strings to see which is "larger" by comparing their graphemes.
+ ///
+ /// This does not compare the size or length of the given strings.
+ ///
+ /// ## Examples
+ ///
+ /// > compare("Anthony", "Anthony")
+ /// order.Eq
+ ///
+ /// > compare("A", "B")
+ /// order.Lt
+ ///
+ pub external fn compare(String, String) -> order.Order =
+ "gleam_stdlib" "compare_strings"
+
+ external fn erl_slice(String, Int, Int) -> String =
+ "string" "slice"
+
+ /// Takes a substring given a start and end Grapheme indexes. Negative indexes
+ /// are taken starting from the *end* of the list.
+ ///
+ /// ## Examples
+ /// > slice(from: "gleam", at_index: 1, length: 2)
+ /// "le"
+ ///
+ /// > slice(from: "gleam", at_index: 1, length: 10)
+ /// "leam"
+ ///
+ /// > slice(from: "gleam", at_index: 10, length: 3)
+ /// ""
+ ///
+ /// > slice(from: "gleam", at_index: -2, length: 2)
+ /// "am"
+ ///
+ /// > slice(from: "gleam", at_index: -12, length: 2)
+ /// ""
+ ///
+ pub fn slice(
+ from string: String,
+ at_index idx: Int,
+ length len: Int,
+ ) -> String {
+ case len < 0 {
+ True -> ""
+ False ->
+ case idx < 0 {
+ True -> {
+ let translated_idx = length(string) + idx
+ case translated_idx < 0 {
+ True -> ""
+ False -> erl_slice(string, translated_idx, len)
+ }
}
+ False -> erl_slice(string, idx, len)
}
- False -> erl_slice(string, idx, len)
- }
+ }
}
-}
-/// Drops contents of the first string that occur before the second string.
-/// If the first string does not contain the second string, the first string is returned.
-///
-/// ## Examples
-/// > crop(from: "The Lone Gunmen", before: "Lone")
-/// "Lone Gunmen"
-///
-pub fn crop(from string: String, before substring: String) -> String {
- string
- |> erl_contains(substring)
- |> dynamic.string()
- |> result.unwrap(string)
-}
+ /// Drops contents of the first string that occur before the second string.
+ /// If the first string does not contain the second string, the first string is returned.
+ ///
+ /// ## Examples
+ /// > crop(from: "The Lone Gunmen", before: "Lone")
+ /// "Lone Gunmen"
+ ///
+ pub fn crop(from string: String, before substring: String) -> String {
+ string
+ |> erl_contains(substring)
+ |> dynamic.string()
+ |> result.unwrap(string)
+ }
-/// Drops *n* Graphemes from the left side of a string.
-///
-/// ## Examples
-/// > drop_left(from: "The Lone Gunmen", up_to: 2)
-/// "e Lone Gunmen"
-///
-pub fn drop_left(from string: String, up_to num_graphemes: Int) -> String {
- case num_graphemes < 0 {
- True -> string
- False -> slice(string, num_graphemes, length(string) - num_graphemes)
+ /// Drops *n* Graphemes from the left side of a string.
+ ///
+ /// ## Examples
+ /// > drop_left(from: "The Lone Gunmen", up_to: 2)
+ /// "e Lone Gunmen"
+ ///
+ pub fn drop_left(from string: String, up_to num_graphemes: Int) -> String {
+ case num_graphemes < 0 {
+ True -> string
+ False -> slice(string, num_graphemes, length(string) - num_graphemes)
+ }
}
-}
-/// Drops *n* Graphemes from the right side of a string.
-///
-/// ## Examples
-/// > drop_right(from: "Cigarette Smoking Man", up_to: 2)
-/// "Cigarette Smoking M"
-///
-pub fn drop_right(from string: String, up_to num_graphemes: Int) -> String {
- case num_graphemes < 0 {
- True -> string
- False -> slice(string, 0, length(string) - num_graphemes)
+ /// Drops *n* Graphemes from the right side of a string.
+ ///
+ /// ## Examples
+ /// > drop_right(from: "Cigarette Smoking Man", up_to: 2)
+ /// "Cigarette Smoking M"
+ ///
+ pub fn drop_right(from string: String, up_to num_graphemes: Int) -> String {
+ case num_graphemes < 0 {
+ True -> string
+ False -> slice(string, 0, length(string) - num_graphemes)
+ }
}
-}
-external fn erl_contains(String, String) -> Dynamic =
- "string" "find"
-
-/// Checks if the first string contains the second.
-///
-/// ## Examples
-///
-/// > contains(does: "theory", contain: "ory")
-/// True
-///
-/// > contains(does: "theory", contain: "the")
-/// True
-///
-/// > contains(does: "theory", contain: "THE")
-/// False
-///
-pub fn contains(does haystack: String, contain needle: String) -> Bool {
- haystack
- |> erl_contains(needle)
- |> dynamic.atom
- |> result.is_error
-}
+ external fn erl_contains(String, String) -> Dynamic =
+ "string" "find"
+
+ /// Checks if the first string contains the second.
+ ///
+ /// ## Examples
+ ///
+ /// > contains(does: "theory", contain: "ory")
+ /// True
+ ///
+ /// > contains(does: "theory", contain: "the")
+ /// True
+ ///
+ /// > contains(does: "theory", contain: "THE")
+ /// False
+ ///
+ pub fn contains(does haystack: String, contain needle: String) -> Bool {
+ haystack
+ |> erl_contains(needle)
+ |> dynamic.atom
+ |> result.is_error
+ }
-/// Checks whether the first string starts with the second one.
-///
-/// ## Examples
-///
-/// > starts_with("theory", "ory")
-/// False
-///
-pub external fn starts_with(String, String) -> Bool =
- "gleam_stdlib" "string_starts_with"
-
-/// Checks whether the first string ends with the second one.
-///
-/// ## Examples
-///
-/// > ends_with("theory", "ory")
-/// True
-///
-pub external fn ends_with(String, String) -> Bool =
- "gleam_stdlib" "string_ends_with"
-
-/// Creates a list of strings by splitting a given string on a given substring.
-///
-/// ## Examples
-///
-/// > split("home/gleam/desktop/", on: "/")
-/// ["home", "gleam", "desktop", ""]
-///
-pub fn split(x: String, on substring: String) -> List(String) {
- x
- |> string_builder.from_string
- |> string_builder.split(on: substring)
- |> list.map(with: string_builder.to_string)
-}
+ /// Checks whether the first string starts with the second one.
+ ///
+ /// ## Examples
+ ///
+ /// > starts_with("theory", "ory")
+ /// False
+ ///
+ pub external fn starts_with(String, String) -> Bool =
+ "gleam_stdlib" "string_starts_with"
+
+ /// Checks whether the first string ends with the second one.
+ ///
+ /// ## Examples
+ ///
+ /// > ends_with("theory", "ory")
+ /// True
+ ///
+ pub external fn ends_with(String, String) -> Bool =
+ "gleam_stdlib" "string_ends_with"
+
+ /// Creates a list of strings by splitting a given string on a given substring.
+ ///
+ /// ## Examples
+ ///
+ /// > split("home/gleam/desktop/", on: "/")
+ /// ["home", "gleam", "desktop", ""]
+ ///
+ pub fn split(x: String, on substring: String) -> List(String) {
+ x
+ |> string_builder.from_string
+ |> string_builder.split(on: substring)
+ |> list.map(with: string_builder.to_string)
+ }
-external fn erl_split(String, String) -> List(String) =
- "string" "split"
-
-/// Splits a string a single time on the given substring.
-///
-/// Returns an error if substring not present.
-///
-/// ## Examples
-///
-/// > split_once("home/gleam/desktop/", on: "/")
-/// Ok(#("home", "gleam/desktop/"))
-///
-/// > split_once("home/gleam/desktop/", on: "?")
-/// Error(Nil)
-///
-pub fn split_once(
- x: String,
- on substring: String,
-) -> Result(#(String, String), Nil) {
- case erl_split(x, substring) {
- [first, rest] -> Ok(#(first, rest))
- _ -> Error(Nil)
+ external fn erl_split(String, String) -> List(String) =
+ "string" "split"
+
+ /// Splits a string a single time on the given substring.
+ ///
+ /// Returns an error if substring not present.
+ ///
+ /// ## Examples
+ ///
+ /// > split_once("home/gleam/desktop/", on: "/")
+ /// Ok(#("home", "gleam/desktop/"))
+ ///
+ /// > split_once("home/gleam/desktop/", on: "?")
+ /// Error(Nil)
+ ///
+ pub fn split_once(
+ x: String,
+ on substring: String,
+ ) -> Result(#(String, String), Nil) {
+ case erl_split(x, substring) {
+ [first, rest] -> Ok(#(first, rest))
+ _ -> Error(Nil)
+ }
}
-}
-/// Creates a new string by joining two strings together.
-///
-/// This function copies both strings and runs in linear time. If you find
-/// yourself joining strings frequently consider using the [string_builder](../string_builder)
-/// module as it can append strings much faster!
-///
-/// ## Examples
-///
-/// > append(to: "butter", suffix: "fly")
-/// "butterfly"
-///
-pub fn append(to first: String, suffix second: String) -> String {
- first
- |> string_builder.from_string
- |> string_builder.append(second)
- |> string_builder.to_string
-}
+ /// Creates a new string by joining two strings together.
+ ///
+ /// This function copies both strings and runs in linear time. If you find
+ /// yourself joining strings frequently consider using the [string_builder](../string_builder)
+ /// module as it can append strings much faster!
+ ///
+ /// ## Examples
+ ///
+ /// > append(to: "butter", suffix: "fly")
+ /// "butterfly"
+ ///
+ pub fn append(to first: String, suffix second: String) -> String {
+ first
+ |> string_builder.from_string
+ |> string_builder.append(second)
+ |> string_builder.to_string
+ }
-/// Creates a new string by joining many strings together.
-///
-/// This function copies both strings and runs in linear time. If you find
-/// yourself joining strings frequently consider using the [string_builder](../string_builder)
-/// module as it can append strings much faster!
-///
-/// ## Examples
-///
-/// > concat(["never", "the", "less"])
-/// "nevertheless"
-///
-pub fn concat(strings: List(String)) -> String {
- strings
- |> string_builder.from_strings
- |> string_builder.to_string
-}
+ /// Creates a new string by joining many strings together.
+ ///
+ /// This function copies both strings and runs in linear time. If you find
+ /// yourself joining strings frequently consider using the [string_builder](../string_builder)
+ /// module as it can append strings much faster!
+ ///
+ /// ## Examples
+ ///
+ /// > concat(["never", "the", "less"])
+ /// "nevertheless"
+ ///
+ pub fn concat(strings: List(String)) -> String {
+ strings
+ |> string_builder.from_strings
+ |> string_builder.to_string
+ }
-/// Creates a new string by repeating a string a given number of times.
-///
-/// This function runs in linear time.
-///
-/// ## Examples
-///
-/// > repeat("ha", times: 3)
-/// "hahaha"
-///
-pub fn repeat(string: String, times times: Int) -> String {
- iterator.repeat(string)
- |> iterator.take(times)
- |> iterator.to_list
- |> concat
-}
+ /// Creates a new string by repeating a string a given number of times.
+ ///
+ /// This function runs in linear time.
+ ///
+ /// ## Examples
+ ///
+ /// > repeat("ha", times: 3)
+ /// "hahaha"
+ ///
+ pub fn repeat(string: String, times times: Int) -> String {
+ iterator.repeat(string)
+ |> iterator.take(times)
+ |> iterator.to_list
+ |> concat
+ }
-/// Joins many strings together with a given separator.
-///
-/// This function runs in linear time.
-///
-/// ## Examples
-///
-/// > join(["home","evan","Desktop"], with: "/")
-/// "home/evan/Desktop"
-///
-pub fn join(strings: List(String), with separator: String) -> String {
- strings
- |> list.intersperse(with: separator)
- |> concat
-}
+ /// Joins many strings together with a given separator.
+ ///
+ /// This function runs in linear time.
+ ///
+ /// ## Examples
+ ///
+ /// > join(["home","evan","Desktop"], with: "/")
+ /// "home/evan/Desktop"
+ ///
+ pub fn join(strings: List(String), with separator: String) -> String {
+ strings
+ |> list.intersperse(with: separator)
+ |> concat
+ }
-type Direction {
- Leading
- Trailing
- Both
-}
+ type Direction {
+ Leading
+ Trailing
+ Both
+ }
-external fn erl_pad(String, Int, Direction, String) -> String =
- "gleam_stdlib" "string_pad"
-
-/// Pads a string on the left until it has at least given number of Graphemes.
-///
-/// ## Examples
-///
-/// > pad_left("121", to: 5, with: ".")
-/// "..121"
-///
-/// > pad_left("121", to: 3, with: ".")
-/// "121"
-///
-/// > pad_left("121", to: 2, with: ".")
-/// "121"
-///
-pub fn pad_left(string: String, to length: Int, with pad_string: String) {
- erl_pad(string, length, Leading, pad_string)
-}
+ external fn erl_pad(String, Int, Direction, String) -> String =
+ "gleam_stdlib" "string_pad"
+
+ /// Pads a string on the left until it has at least given number of Graphemes.
+ ///
+ /// ## Examples
+ ///
+ /// > pad_left("121", to: 5, with: ".")
+ /// "..121"
+ ///
+ /// > pad_left("121", to: 3, with: ".")
+ /// "121"
+ ///
+ /// > pad_left("121", to: 2, with: ".")
+ /// "121"
+ ///
+ pub fn pad_left(string: String, to length: Int, with pad_string: String) {
+ erl_pad(string, length, Leading, pad_string)
+ }
-/// Pads a string on the right until it has a given length.
-///
-/// ## Examples
-///
-/// > pad_right("121", to: 5, with: ".")
-/// "121.."
-///
-/// > pad_right("121", to: 3, with: ".")
-/// "121"
-///
-/// > pad_right("121", to: 2, with: ".")
-/// "121"
-///
-pub fn pad_right(string: String, to length: Int, with pad_string: String) {
- erl_pad(string, length, Trailing, pad_string)
-}
+ /// Pads a string on the right until it has a given length.
+ ///
+ /// ## Examples
+ ///
+ /// > pad_right("121", to: 5, with: ".")
+ /// "121.."
+ ///
+ /// > pad_right("121", to: 3, with: ".")
+ /// "121"
+ ///
+ /// > pad_right("121", to: 2, with: ".")
+ /// "121"
+ ///
+ pub fn pad_right(string: String, to length: Int, with pad_string: String) {
+ erl_pad(string, length, Trailing, pad_string)
+ }
-external fn erl_trim(String, Direction) -> String =
- "string" "trim"
-
-/// Removes whitespace on both sides of a String.
-///
-/// ## Examples
-///
-/// > trim(" hats \n")
-/// "hats"
-///
-pub fn trim(string: String) -> String {
- erl_trim(string, Both)
-}
+ external fn erl_trim(String, Direction) -> String =
+ "string" "trim"
+
+ /// Removes whitespace on both sides of a String.
+ ///
+ /// ## Examples
+ ///
+ /// > trim(" hats \n")
+ /// "hats"
+ ///
+ pub fn trim(string: String) -> String {
+ erl_trim(string, Both)
+ }
-/// Removes whitespace on the left of a String.
-///
-/// ## Examples
-///
-/// > trim_left(" hats \n")
-/// "hats \n"
-///
-pub fn trim_left(string: String) -> String {
- erl_trim(string, Leading)
-}
+ /// Removes whitespace on the left of a String.
+ ///
+ /// ## Examples
+ ///
+ /// > trim_left(" hats \n")
+ /// "hats \n"
+ ///
+ pub fn trim_left(string: String) -> String {
+ erl_trim(string, Leading)
+ }
-/// Removes whitespace on the right of a String.
-///
-/// ## Examples
-///
-/// > trim_right(" hats \n")
-/// " hats"
-///
-pub fn trim_right(string: String) -> String {
- erl_trim(string, Trailing)
-}
+ /// Removes whitespace on the right of a String.
+ ///
+ /// ## Examples
+ ///
+ /// > trim_right(" hats \n")
+ /// " hats"
+ ///
+ pub fn trim_right(string: String) -> String {
+ erl_trim(string, Trailing)
+ }
-/// Splits a non-empty string into its head and tail. This lets you
-/// pattern match on strings exactly as you would with lists.
-///
-/// ## Examples
-/// > pop_grapheme("gleam")
-/// Ok(#("g", "leam"))
-///
-/// > pop_grapheme("")
-/// Error(Nil)
-///
-pub external fn pop_grapheme(string: String) -> Result(#(String, String), Nil) =
- "gleam_stdlib" "string_pop_grapheme"
-
-/// Converts a string to a list of Graphemes.
-///
-/// > to_graphemes("abc")
-/// ["a", "b", "c"]
-///
-pub fn to_graphemes(string: String) -> List(String) {
- case pop_grapheme(string) {
- Ok(#(grapheme, rest)) -> [grapheme, ..to_graphemes(rest)]
- _ -> []
+ /// Splits a non-empty string into its head and tail. This lets you
+ /// pattern match on strings exactly as you would with lists.
+ ///
+ /// ## Examples
+ /// > pop_grapheme("gleam")
+ /// Ok(#("g", "leam"))
+ ///
+ /// > pop_grapheme("")
+ /// Error(Nil)
+ ///
+ pub external fn pop_grapheme(string: String) -> Result(#(String, String), Nil) =
+ "gleam_stdlib" "string_pop_grapheme"
+
+ /// Converts a string to a list of Graphemes.
+ ///
+ /// > to_graphemes("abc")
+ /// ["a", "b", "c"]
+ ///
+ pub fn to_graphemes(string: String) -> List(String) {
+ case pop_grapheme(string) {
+ Ok(#(grapheme, rest)) -> [grapheme, ..to_graphemes(rest)]
+ _ -> []
+ }
}
-}
-external fn int_to_utf_codepoint(Int) -> UtfCodepoint =
- "gleam_stdlib" "identity"
-
-/// Converts an integer to a UtfCodepoint
-///
-/// Returns an error if the integer does not represent a valid UTF codepoint.
-///
-pub fn utf_codepoint(value: Int) -> Result(UtfCodepoint, Nil) {
- case value {
- i if i > 1114111 -> Error(Nil)
- 65534 | 65535 -> Error(Nil)
- i if i >= 55296 && i <= 57343 -> Error(Nil)
- i -> Ok(int_to_utf_codepoint(i))
+ external fn int_to_utf_codepoint(Int) -> UtfCodepoint =
+ "gleam_stdlib" "identity"
+
+ /// Converts an integer to a UtfCodepoint
+ ///
+ /// Returns an error if the integer does not represent a valid UTF codepoint.
+ ///
+ pub fn utf_codepoint(value: Int) -> Result(UtfCodepoint, Nil) {
+ case value {
+ i if i > 1114111 -> Error(Nil)
+ 65534 | 65535 -> Error(Nil)
+ i if i >= 55296 && i <= 57343 -> Error(Nil)
+ i -> Ok(int_to_utf_codepoint(i))
+ }
}
}
diff --git a/src/gleam/string_builder.gleam b/src/gleam/string_builder.gleam
index 36970b2..c09d60b 100644
--- a/src/gleam/string_builder.gleam
+++ b/src/gleam/string_builder.gleam
@@ -1,168 +1,170 @@
-/// StringBuilder is a type used for efficiently building strings.
-///
-/// When we append one string to another the strings must be copied to a
-/// new location in memory so that they can sit together. This behaviour
-/// enables efficient reading of the string but copying can be expensive,
-/// especially if we want to join many strings together.
-///
-/// StringBuilder is different in that it can be joined together in constant time
-/// using minimal memory, and then can be efficiently converted to a string
-/// using the `to_string` function.
-///
-pub external type StringBuilder
-
-/// Prepends a String onto the start of some StringBuilder.
-///
-/// Runs in constant time.
-///
-pub external fn prepend(to: StringBuilder, prefix: String) -> StringBuilder =
- "gleam_stdlib" "iodata_prepend"
-
-/// Appends a String onto the end of some StringBuilder.
-///
-/// Runs in constant time.
-///
-pub external fn append(to: StringBuilder, suffix: String) -> StringBuilder =
- "gleam_stdlib" "iodata_append"
-
-/// Prepends some StringBuilder onto the start of another.
-///
-/// Runs in constant time.
-///
-pub external fn prepend_builder(
- to: StringBuilder,
- prefix: StringBuilder,
-) -> StringBuilder =
- "gleam_stdlib" "iodata_prepend"
-
-/// Appends some StringBuilder onto the end of another.
-///
-/// Runs in constant time.
-///
-pub external fn append_builder(
- to: StringBuilder,
- suffix: StringBuilder,
-) -> StringBuilder =
- "gleam_stdlib" "iodata_append"
-
-/// Converts a list of strings into a builder.
-///
-/// Runs in constant time.
-///
-pub external fn from_strings(List(String)) -> StringBuilder =
- "gleam_stdlib" "identity"
-
-/// Joins a list of builders into a single builder.
-///
-/// Runs in constant time.
-///
-pub external fn concat(List(StringBuilder)) -> StringBuilder =
- "gleam_stdlib" "identity"
-
-/// Converts a string into a builder.
-///
-/// Runs in constant time.
-///
-pub external fn from_string(String) -> StringBuilder =
- "gleam_stdlib" "identity"
-
-/// Turns an `StringBuilder` into a `String`
-///
-/// This function is implemented natively by the virtual machine and is highly
-/// optimised.
-///
-pub external fn to_string(StringBuilder) -> String =
- "erlang" "iolist_to_binary"
-
-/// Returns the size of the StringBuilder in bytes.
-///
-pub external fn byte_size(StringBuilder) -> Int =
- "erlang" "iolist_size"
-
-/// Creates a builder containing the textual representation of a given float.
-///
-pub external fn from_float(Float) -> StringBuilder =
- "io_lib_format" "fwrite_g"
-
-/// Converts a builder to a new builder where the contents have been
-/// lowercased.
-///
-pub external fn lowercase(StringBuilder) -> StringBuilder =
- "string" "lowercase"
-
-/// Converts a builder to a new builder where the contents have been
-/// uppercased.
-///
-pub external fn uppercase(StringBuilder) -> StringBuilder =
- "string" "uppercase"
-
-/// Converts a builder to a new builder with the contents reversed.
-///
-pub external fn reverse(StringBuilder) -> StringBuilder =
- "string" "reverse"
-
-type Direction {
- All
+if erlang {
+ /// StringBuilder is a type used for efficiently building strings.
+ ///
+ /// When we append one string to another the strings must be copied to a
+ /// new location in memory so that they can sit together. This behaviour
+ /// enables efficient reading of the string but copying can be expensive,
+ /// especially if we want to join many strings together.
+ ///
+ /// StringBuilder is different in that it can be joined together in constant time
+ /// using minimal memory, and then can be efficiently converted to a string
+ /// using the `to_string` function.
+ ///
+ pub external type StringBuilder
+
+ /// Prepends a String onto the start of some StringBuilder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn prepend(to: StringBuilder, prefix: String) -> StringBuilder =
+ "gleam_stdlib" "iodata_prepend"
+
+ /// Appends a String onto the end of some StringBuilder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn append(to: StringBuilder, suffix: String) -> StringBuilder =
+ "gleam_stdlib" "iodata_append"
+
+ /// Prepends some StringBuilder onto the start of another.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn prepend_builder(
+ to: StringBuilder,
+ prefix: StringBuilder,
+ ) -> StringBuilder =
+ "gleam_stdlib" "iodata_prepend"
+
+ /// Appends some StringBuilder onto the end of another.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn append_builder(
+ to: StringBuilder,
+ suffix: StringBuilder,
+ ) -> StringBuilder =
+ "gleam_stdlib" "iodata_append"
+
+ /// Converts a list of strings into a builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn from_strings(List(String)) -> StringBuilder =
+ "gleam_stdlib" "identity"
+
+ /// Joins a list of builders into a single builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn concat(List(StringBuilder)) -> StringBuilder =
+ "gleam_stdlib" "identity"
+
+ /// Converts a string into a builder.
+ ///
+ /// Runs in constant time.
+ ///
+ pub external fn from_string(String) -> StringBuilder =
+ "gleam_stdlib" "identity"
+
+ /// Turns an `StringBuilder` into a `String`
+ ///
+ /// This function is implemented natively by the virtual machine and is highly
+ /// optimised.
+ ///
+ pub external fn to_string(StringBuilder) -> String =
+ "erlang" "iolist_to_binary"
+
+ /// Returns the size of the StringBuilder in bytes.
+ ///
+ pub external fn byte_size(StringBuilder) -> Int =
+ "erlang" "iolist_size"
+
+ /// Creates a builder containing the textual representation of a given float.
+ ///
+ pub external fn from_float(Float) -> StringBuilder =
+ "io_lib_format" "fwrite_g"
+
+ /// Converts a builder to a new builder where the contents have been
+ /// lowercased.
+ ///
+ pub external fn lowercase(StringBuilder) -> StringBuilder =
+ "string" "lowercase"
+
+ /// Converts a builder to a new builder where the contents have been
+ /// uppercased.
+ ///
+ pub external fn uppercase(StringBuilder) -> StringBuilder =
+ "string" "uppercase"
+
+ /// Converts a builder to a new builder with the contents reversed.
+ ///
+ pub external fn reverse(StringBuilder) -> StringBuilder =
+ "string" "reverse"
+
+ type Direction {
+ All
+ }
+
+ external fn erl_split(StringBuilder, String, Direction) -> List(StringBuilder) =
+ "string" "split"
+
+ /// Splits a builder on a given pattern into a list of builders.
+ ///
+ pub fn split(iodata: StringBuilder, on pattern: String) -> List(StringBuilder) {
+ erl_split(iodata, pattern, All)
+ }
+
+ external fn erl_replace(
+ StringBuilder,
+ String,
+ String,
+ Direction,
+ ) -> StringBuilder =
+ "string" "replace"
+
+ /// Replaces all instances of a pattern with a given string substitute.
+ ///
+ pub fn replace(
+ in iodata: StringBuilder,
+ each pattern: String,
+ with substitute: String,
+ ) -> StringBuilder {
+ erl_replace(iodata, pattern, substitute, All)
+ }
+
+ /// Compares two builders to determine if they have the same textual content.
+ ///
+ /// Comparing two iodata using the `==` operator may return False even if they
+ /// have the same content as they may have been build in different ways, so
+ /// using this function is often preferred.
+ ///
+ /// ## Examples
+ ///
+ /// > from_strings(["a", "b"]) == new("ab")
+ /// False
+ ///
+ /// > is_equal(from_strings(["a", "b"]), new("ab"))
+ /// True
+ ///
+ ///
+ pub external fn is_equal(StringBuilder, StringBuilder) -> Bool =
+ "string" "equal"
+
+ /// Inspects a builder to determine if it is equivalent to an empty string.
+ ///
+ /// ## Examples
+ ///
+ /// > new("ok") |> is_empty
+ /// False
+ ///
+ /// > new("") |> is_empty
+ /// True
+ ///
+ /// > from_strings([]) |> is_empty
+ /// True
+ ///
+ ///
+ pub external fn is_empty(StringBuilder) -> Bool =
+ "string" "is_empty"
}
-
-external fn erl_split(StringBuilder, String, Direction) -> List(StringBuilder) =
- "string" "split"
-
-/// Splits a builder on a given pattern into a list of builders.
-///
-pub fn split(iodata: StringBuilder, on pattern: String) -> List(StringBuilder) {
- erl_split(iodata, pattern, All)
-}
-
-external fn erl_replace(
- StringBuilder,
- String,
- String,
- Direction,
-) -> StringBuilder =
- "string" "replace"
-
-/// Replaces all instances of a pattern with a given string substitute.
-///
-pub fn replace(
- in iodata: StringBuilder,
- each pattern: String,
- with substitute: String,
-) -> StringBuilder {
- erl_replace(iodata, pattern, substitute, All)
-}
-
-/// Compares two builders to determine if they have the same textual content.
-///
-/// Comparing two iodata using the `==` operator may return False even if they
-/// have the same content as they may have been build in different ways, so
-/// using this function is often preferred.
-///
-/// ## Examples
-///
-/// > from_strings(["a", "b"]) == new("ab")
-/// False
-///
-/// > is_equal(from_strings(["a", "b"]), new("ab"))
-/// True
-///
-///
-pub external fn is_equal(StringBuilder, StringBuilder) -> Bool =
- "string" "equal"
-
-/// Inspects a builder to determine if it is equivalent to an empty string.
-///
-/// ## Examples
-///
-/// > new("ok") |> is_empty
-/// False
-///
-/// > new("") |> is_empty
-/// True
-///
-/// > from_strings([]) |> is_empty
-/// True
-///
-///
-pub external fn is_empty(StringBuilder) -> Bool =
- "string" "is_empty"
diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam
index a65d753..b40b381 100644
--- a/src/gleam/uri.gleam
+++ b/src/gleam/uri.gleam
@@ -7,351 +7,353 @@
//// Query encoding (Form encoding) is defined in the w3c specification.
//// https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data
-import gleam/list
-import gleam/result
-import gleam/option.{None, Option, Some}
-import gleam/string
-import gleam/dynamic.{Dynamic}
-import gleam/map.{Map}
-import gleam/function
-import gleam/pair
+if erlang {
+ import gleam/list
+ import gleam/result
+ import gleam/option.{None, Option, Some}
+ import gleam/string
+ import gleam/dynamic.{Dynamic}
+ import gleam/map.{Map}
+ import gleam/function
+ import gleam/pair
-/// Type representing holding the parsed components of an URI.
-/// All components of a URI are optional, except the path.
-///
-pub type Uri {
- Uri(
- scheme: Option(String),
- userinfo: Option(String),
- host: Option(String),
- port: Option(Int),
- path: String,
- query: Option(String),
- fragment: Option(String),
- )
-}
-
-pub external fn erl_parse(String) -> Dynamic =
- "uri_string" "parse"
+ /// Type representing holding the parsed components of an URI.
+ /// All components of a URI are optional, except the path.
+ ///
+ pub type Uri {
+ Uri(
+ scheme: Option(String),
+ userinfo: Option(String),
+ host: Option(String),
+ port: Option(Int),
+ path: String,
+ query: Option(String),
+ fragment: Option(String),
+ )
+ }
-type UriKey {
- Scheme
- Userinfo
- Host
- Port
- Path
- Query
- Fragment
-}
+ pub external fn erl_parse(String) -> Dynamic =
+ "uri_string" "parse"
-/// Parses a compliant URI string into the `Uri` Type.
-/// If the string is not a valid URI string then an error is returned.
-///
-/// The opposite operation is `uri.to_string`
-///
-/// ## Examples
-///
-/// ```
-/// > parse("https://example.com:1234/a/b?query=true#fragment")
-///
-/// Ok(Uri(scheme: Some("https"), ...))
-/// ```
-///
-pub fn parse(string: String) -> Result(Uri, Nil) {
- try uri_map =
- dynamic.map(erl_parse(string))
- |> result.nil_error
- let get = fn(k: UriKey, decode_type: dynamic.Decoder(t)) -> Option(t) {
- uri_map
- |> map.get(dynamic.from(k))
- |> result.then(function.compose(decode_type, result.nil_error))
- |> option.from_result
+ type UriKey {
+ Scheme
+ Userinfo
+ Host
+ Port
+ Path
+ Query
+ Fragment
}
- let uri =
- Uri(
- scheme: get(Scheme, dynamic.string),
- userinfo: get(Userinfo, dynamic.string),
- host: get(Host, dynamic.string),
- port: get(Port, dynamic.int),
- path: option.unwrap(get(Path, dynamic.string), ""),
- query: get(Query, dynamic.string),
- fragment: get(Fragment, dynamic.string),
- )
- Ok(uri)
-}
+ /// Parses a compliant URI string into the `Uri` Type.
+ /// If the string is not a valid URI string then an error is returned.
+ ///
+ /// The opposite operation is `uri.to_string`
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > parse("https://example.com:1234/a/b?query=true#fragment")
+ ///
+ /// Ok(Uri(scheme: Some("https"), ...))
+ /// ```
+ ///
+ pub fn parse(string: String) -> Result(Uri, Nil) {
+ try uri_map =
+ dynamic.map(erl_parse(string))
+ |> result.nil_error
+ let get = fn(k: UriKey, decode_type: dynamic.Decoder(t)) -> Option(t) {
+ uri_map
+ |> map.get(dynamic.from(k))
+ |> result.then(function.compose(decode_type, result.nil_error))
+ |> option.from_result
+ }
-external fn erl_parse_query(String) -> Dynamic =
- "uri_string" "dissect_query"
+ let uri =
+ Uri(
+ scheme: get(Scheme, dynamic.string),
+ userinfo: get(Userinfo, dynamic.string),
+ host: get(Host, dynamic.string),
+ port: get(Port, dynamic.int),
+ path: option.unwrap(get(Path, dynamic.string), ""),
+ query: get(Query, dynamic.string),
+ fragment: get(Fragment, dynamic.string),
+ )
+ Ok(uri)
+ }
-/// Parses an urlencoded query string into a list of key value pairs.
-/// Returns an error for invalid encoding.
-///
-/// The opposite operation is `uri.query_to_string`.
-///
-/// ## Examples
-///
-/// ```
-/// > parse_query("a=1&b=2")
-///
-/// Ok([#("a", "1"), #("b", "2")])
-/// ```
-///
-pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) {
- let bool_value = fn(x) { result.map(dynamic.bool(x), fn(_) { "" }) }
- let query_param = dynamic.typed_tuple2(
- _,
- dynamic.string,
- dynamic.any(_, of: [dynamic.string, bool_value]),
- )
+ external fn erl_parse_query(String) -> Dynamic =
+ "uri_string" "dissect_query"
- query
- |> erl_parse_query
- |> dynamic.typed_list(of: query_param)
- |> result.nil_error
-}
+ /// Parses an urlencoded query string into a list of key value pairs.
+ /// Returns an error for invalid encoding.
+ ///
+ /// The opposite operation is `uri.query_to_string`.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > parse_query("a=1&b=2")
+ ///
+ /// Ok([#("a", "1"), #("b", "2")])
+ /// ```
+ ///
+ pub fn parse_query(query: String) -> Result(List(#(String, String)), Nil) {
+ let bool_value = fn(x) { result.map(dynamic.bool(x), fn(_) { "" }) }
+ let query_param = dynamic.typed_tuple2(
+ _,
+ dynamic.string,
+ dynamic.any(_, of: [dynamic.string, bool_value]),
+ )
-type Encoding {
- Utf8
-}
+ query
+ |> erl_parse_query
+ |> dynamic.typed_list(of: query_param)
+ |> result.nil_error
+ }
-type ErlQueryToStringOption {
- Encoding(Encoding)
-}
+ type Encoding {
+ Utf8
+ }
-external fn erl_query_to_string(
- List(#(String, String)),
- List(ErlQueryToStringOption),
-) -> Dynamic =
- "uri_string" "compose_query"
+ type ErlQueryToStringOption {
+ Encoding(Encoding)
+ }
-/// Encodes a list of key value pairs as a URI query string.
-///
-/// The opposite operation is `uri.parse_query`.
-///
-/// ## Examples
-///
-/// ```
-/// > query_to_string([#("a", "1"), #("b", "2")])
-///
-/// "a=1&b=2"
-/// ```
-///
-pub fn query_to_string(query: List(#(String, String))) -> String {
- query
- |> erl_query_to_string([Encoding(Utf8)])
- |> dynamic.string
- |> result.unwrap("")
-}
+ external fn erl_query_to_string(
+ List(#(String, String)),
+ List(ErlQueryToStringOption),
+ ) -> Dynamic =
+ "uri_string" "compose_query"
-/// Encodes a string into a percent encoded representation.
-/// Note that this encodes space as +.
-///
-/// ## Examples
-///
-/// ```
-/// > percent_encode("100% great")
-///
-/// "100%25+great"
-/// ```
-///
-pub fn percent_encode(value: String) -> String {
- query_to_string([#("k", value)])
- |> string.replace(each: "k=", with: "")
-}
+ /// Encodes a list of key value pairs as a URI query string.
+ ///
+ /// The opposite operation is `uri.parse_query`.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > query_to_string([#("a", "1"), #("b", "2")])
+ ///
+ /// "a=1&b=2"
+ /// ```
+ ///
+ pub fn query_to_string(query: List(#(String, String))) -> String {
+ query
+ |> erl_query_to_string([Encoding(Utf8)])
+ |> dynamic.string
+ |> result.unwrap("")
+ }
-/// Decodes a percent encoded string.
-///
-/// ## Examples
-///
-/// ```
-/// > percent_decode("100%25+great")
-///
-/// Ok("100% great")
-/// ```
-///
-pub fn percent_decode(value: String) -> Result(String, Nil) {
- string.concat(["k=", value])
- |> parse_query
- |> result.then(list.head)
- |> result.map(pair.second)
-}
+ /// Encodes a string into a percent encoded representation.
+ /// Note that this encodes space as +.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > percent_encode("100% great")
+ ///
+ /// "100%25+great"
+ /// ```
+ ///
+ pub fn percent_encode(value: String) -> String {
+ query_to_string([#("k", value)])
+ |> string.replace(each: "k=", with: "")
+ }
+
+ /// Decodes a percent encoded string.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > percent_decode("100%25+great")
+ ///
+ /// Ok("100% great")
+ /// ```
+ ///
+ pub fn percent_decode(value: String) -> Result(String, Nil) {
+ string.concat(["k=", value])
+ |> parse_query
+ |> result.then(list.head)
+ |> result.map(pair.second)
+ }
-fn do_remove_dot_segments(
- input: List(String),
- accumulator: List(String),
-) -> List(String) {
- case input {
- [] -> list.reverse(accumulator)
- [segment, ..rest] -> {
- let accumulator = case segment, accumulator {
- "", accumulator -> accumulator
- ".", accumulator -> accumulator
- "..", [] -> []
- "..", [_, ..accumulator] -> accumulator
- segment, accumulator -> [segment, ..accumulator]
+ fn do_remove_dot_segments(
+ input: List(String),
+ accumulator: List(String),
+ ) -> List(String) {
+ case input {
+ [] -> list.reverse(accumulator)
+ [segment, ..rest] -> {
+ let accumulator = case segment, accumulator {
+ "", accumulator -> accumulator
+ ".", accumulator -> accumulator
+ "..", [] -> []
+ "..", [_, ..accumulator] -> accumulator
+ segment, accumulator -> [segment, ..accumulator]
+ }
+ do_remove_dot_segments(rest, accumulator)
}
- do_remove_dot_segments(rest, accumulator)
}
}
-}
-fn remove_dot_segments(input: List(String)) -> List(String) {
- do_remove_dot_segments(input, [])
-}
+ fn remove_dot_segments(input: List(String)) -> List(String) {
+ do_remove_dot_segments(input, [])
+ }
-/// Splits the path section of a URI into it's constituent segments.
-///
-/// Removes empty segments and resolves dot-segments as specified in
-/// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.
-///
-/// ## Examples
-///
-/// ```
-/// > path_segments("/users/1")
-///
-/// ["users" ,"1"]
-/// ```
-///
-pub fn path_segments(path: String) -> List(String) {
- remove_dot_segments(string.split(path, "/"))
-}
+ /// Splits the path section of a URI into it's constituent segments.
+ ///
+ /// Removes empty segments and resolves dot-segments as specified in
+ /// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > path_segments("/users/1")
+ ///
+ /// ["users" ,"1"]
+ /// ```
+ ///
+ pub fn path_segments(path: String) -> List(String) {
+ remove_dot_segments(string.split(path, "/"))
+ }
-external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
- "uri_string" "recompose"
+ external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
+ "uri_string" "recompose"
-/// Encodes a `Uri` value as a URI string.
-///
-/// The opposite operation is `uri.parse`.
-///
-/// ## Examples
-///
-/// ```
-/// > let uri = Uri(Some("http"), None, Some("example.com"), ...)
-/// > to_string(uri)
-///
-/// "https://example.com"
-/// ```
-///
-pub fn to_string(uri: Uri) -> String {
- let field = fn(key: UriKey, value: Option(anything)) -> Result(
- #(UriKey, Dynamic),
- Nil,
- ) {
- case value {
- Some(v) -> Ok(#(key, dynamic.from(v)))
- None -> Error(Nil)
+ /// Encodes a `Uri` value as a URI string.
+ ///
+ /// The opposite operation is `uri.parse`.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > let uri = Uri(Some("http"), None, Some("example.com"), ...)
+ /// > to_string(uri)
+ ///
+ /// "https://example.com"
+ /// ```
+ ///
+ pub fn to_string(uri: Uri) -> String {
+ let field = fn(key: UriKey, value: Option(anything)) -> Result(
+ #(UriKey, Dynamic),
+ Nil,
+ ) {
+ case value {
+ Some(v) -> Ok(#(key, dynamic.from(v)))
+ None -> Error(Nil)
+ }
}
- }
- [
- field(Scheme, uri.scheme),
- field(Userinfo, uri.userinfo),
- field(Host, uri.host),
- field(Port, uri.port),
- field(Path, option.Some(uri.path)),
- field(Query, uri.query),
- field(Fragment, uri.fragment),
- ]
- |> list.filter_map(fn(x) { x })
- |> map.from_list
- |> erl_to_string
- |> dynamic.string
- |> result.unwrap("")
-}
+ [
+ field(Scheme, uri.scheme),
+ field(Userinfo, uri.userinfo),
+ field(Host, uri.host),
+ field(Port, uri.port),
+ field(Path, option.Some(uri.path)),
+ field(Query, uri.query),
+ field(Fragment, uri.fragment),
+ ]
+ |> list.filter_map(fn(x) { x })
+ |> map.from_list
+ |> erl_to_string
+ |> dynamic.string
+ |> result.unwrap("")
+ }
-/// Fetches the origin of a uri
-///
-/// Return the origin of a uri as defined in
-/// https://tools.ietf.org/html/rfc6454
-///
-/// The supported uri schemes are `http` and `https`
-/// Urls without a scheme will return Error
-///
-/// ## Examples
-///
-/// ```
-/// > assert Ok(uri) = parse("http://example.com/path?foo#bar")
-/// > origin(uri)
-///
-/// Ok("http://example.com")
-/// ```
-///
-pub fn origin(uri: Uri) -> Result(String, Nil) {
- let Uri(scheme: scheme, host: host, port: port, ..) = uri
- case scheme {
- Some("https") | Some("http") -> {
- let origin = Uri(scheme, None, host, port, "", None, None)
- Ok(to_string(origin))
+ /// Fetches the origin of a uri
+ ///
+ /// Return the origin of a uri as defined in
+ /// https://tools.ietf.org/html/rfc6454
+ ///
+ /// The supported uri schemes are `http` and `https`
+ /// Urls without a scheme will return Error
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// > assert Ok(uri) = parse("http://example.com/path?foo#bar")
+ /// > origin(uri)
+ ///
+ /// Ok("http://example.com")
+ /// ```
+ ///
+ pub fn origin(uri: Uri) -> Result(String, Nil) {
+ let Uri(scheme: scheme, host: host, port: port, ..) = uri
+ case scheme {
+ Some("https") | Some("http") -> {
+ let origin = Uri(scheme, None, host, port, "", None, None)
+ Ok(to_string(origin))
+ }
+ _ -> Error(Nil)
}
- _ -> Error(Nil)
}
-}
-fn drop_last(elements: List(a)) -> List(a) {
- list.take(from: elements, up_to: list.length(elements) - 1)
-}
+ fn drop_last(elements: List(a)) -> List(a) {
+ list.take(from: elements, up_to: list.length(elements) - 1)
+ }
-fn join_segments(segments: List(String)) -> String {
- string.join(["", ..segments], "/")
-}
+ fn join_segments(segments: List(String)) -> String {
+ string.join(["", ..segments], "/")
+ }
-/// Resolves a uri with respect to the given base uri
-///
-/// The base uri must be an absolute uri or this function will return an error.
-/// The algorithm for merging uris is described in [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2)
-pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) {
- case base {
- Uri(scheme: Some(_), host: Some(_), ..) ->
- case relative {
- Uri(host: Some(_), ..) -> {
- let path =
- string.split(relative.path, "/")
- |> remove_dot_segments()
- |> join_segments()
- let resolved =
- Uri(
- option.or(relative.scheme, base.scheme),
- None,
- relative.host,
- relative.port,
- path,
- relative.query,
- relative.fragment,
- )
- Ok(resolved)
- }
- Uri(scheme: None, host: None, ..) -> {
- let #(new_path, new_query) = case relative.path {
- "" -> #(base.path, option.or(relative.query, base.query))
- _ -> {
- let path_segments = case string.starts_with(relative.path, "/") {
- True -> string.split(relative.path, "/")
- False ->
- string.split(base.path, "/")
- |> drop_last()
- |> list.append(string.split(relative.path, "/"))
+ /// Resolves a uri with respect to the given base uri
+ ///
+ /// The base uri must be an absolute uri or this function will return an error.
+ /// The algorithm for merging uris is described in [RFC 3986](https://tools.ietf.org/html/rfc3986#section-5.2)
+ pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) {
+ case base {
+ Uri(scheme: Some(_), host: Some(_), ..) ->
+ case relative {
+ Uri(host: Some(_), ..) -> {
+ let path =
+ string.split(relative.path, "/")
+ |> remove_dot_segments()
+ |> join_segments()
+ let resolved =
+ Uri(
+ option.or(relative.scheme, base.scheme),
+ None,
+ relative.host,
+ relative.port,
+ path,
+ relative.query,
+ relative.fragment,
+ )
+ Ok(resolved)
+ }
+ Uri(scheme: None, host: None, ..) -> {
+ let #(new_path, new_query) = case relative.path {
+ "" -> #(base.path, option.or(relative.query, base.query))
+ _ -> {
+ let path_segments = case string.starts_with(relative.path, "/") {
+ True -> string.split(relative.path, "/")
+ False ->
+ string.split(base.path, "/")
+ |> drop_last()
+ |> list.append(string.split(relative.path, "/"))
+ }
+ let path =
+ path_segments
+ |> remove_dot_segments()
+ |> join_segments()
+ #(path, relative.query)
}
- let path =
- path_segments
- |> remove_dot_segments()
- |> join_segments()
- #(path, relative.query)
}
+ let resolved =
+ Uri(
+ base.scheme,
+ None,
+ base.host,
+ base.port,
+ new_path,
+ new_query,
+ relative.fragment,
+ )
+ Ok(resolved)
}
- let resolved =
- Uri(
- base.scheme,
- None,
- base.host,
- base.port,
- new_path,
- new_query,
- relative.fragment,
- )
- Ok(resolved)
}
- }
- _ -> Error(Nil)
+ _ -> Error(Nil)
+ }
}
}
diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl
index 10d3752..fe70eea 100644
--- a/src/gleam_stdlib.erl
+++ b/src/gleam_stdlib.erl
@@ -14,10 +14,18 @@
decode_bit_string/1, compile_regex/2, regex_match/2, regex_split/2,
regex_scan/2, base_decode64/1, wrap_list/1, rescue/1, get_line/1]).
-should_equal(Actual, Expected) -> ?assertEqual(Expected, Actual).
-should_not_equal(Actual, Expected) -> ?assertNotEqual(Expected, Actual).
-should_be_ok(A) -> ?assertMatch({ok, _}, A).
-should_be_error(A) -> ?assertMatch({error, _}, A).
+should_equal(Actual, Expected) ->
+ ?assertEqual(Expected, Actual),
+ nil.
+should_not_equal(Actual, Expected) ->
+ ?assertNotEqual(Expected, Actual),
+ nil.
+should_be_ok(A) ->
+ ?assertMatch({ok, _}, A),
+ nil.
+should_be_error(A) ->
+ ?assertMatch({error, _}, A),
+ nil.
map_get(Map, Key) ->
case maps:find(Key, Map) of
diff --git a/src/gleam_stdlib.js b/src/gleam_stdlib.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/gleam_stdlib.js
diff --git a/test/gleam/atom_test.gleam b/test/gleam/atom_test.gleam
index 228791d..ccc34ed 100644
--- a/test/gleam/atom_test.gleam
+++ b/test/gleam/atom_test.gleam
@@ -1,45 +1,47 @@
-import gleam/atom
-import gleam/should
-
-pub fn from_string_test() {
- atom.create_from_string("this is an existing atom")
-
- "this is an existing atom"
- |> atom.from_string
- |> should.be_ok
-
- "this is not an atom we have seen before"
- |> atom.from_string
- |> should.equal(Error(atom.AtomNotLoaded))
-}
-
-pub fn create_from_string_test() {
- "ok"
- |> atom.create_from_string
- |> Ok
- |> should.equal(atom.from_string("ok"))
-
- "expect"
- |> atom.create_from_string
- |> Ok
- |> should.equal(atom.from_string("expect"))
-
- "this is another atom we have not seen before"
- |> atom.create_from_string
- |> Ok
- |> should.equal(atom.from_string(
- "this is another atom we have not seen before",
- ))
-}
-
-pub fn to_string_test() {
- "ok"
- |> atom.create_from_string
- |> atom.to_string
- |> should.equal("ok")
-
- "expect"
- |> atom.create_from_string
- |> atom.to_string
- |> should.equal("expect")
+if erlang {
+ import gleam/atom
+ import gleam/should
+
+ pub fn from_string_test() {
+ atom.create_from_string("this is an existing atom")
+
+ "this is an existing atom"
+ |> atom.from_string
+ |> should.be_ok
+
+ "this is not an atom we have seen before"
+ |> atom.from_string
+ |> should.equal(Error(atom.AtomNotLoaded))
+ }
+
+ pub fn create_from_string_test() {
+ "ok"
+ |> atom.create_from_string
+ |> Ok
+ |> should.equal(atom.from_string("ok"))
+
+ "expect"
+ |> atom.create_from_string
+ |> Ok
+ |> should.equal(atom.from_string("expect"))
+
+ "this is another atom we have not seen before"
+ |> atom.create_from_string
+ |> Ok
+ |> should.equal(atom.from_string(
+ "this is another atom we have not seen before",
+ ))
+ }
+
+ pub fn to_string_test() {
+ "ok"
+ |> atom.create_from_string
+ |> atom.to_string
+ |> should.equal("ok")
+
+ "expect"
+ |> atom.create_from_string
+ |> atom.to_string
+ |> should.equal("expect")
+ }
}
diff --git a/test/gleam/base_test.gleam b/test/gleam/base_test.gleam
index 3d2b7c6..80f0024 100644
--- a/test/gleam/base_test.gleam
+++ b/test/gleam/base_test.gleam
@@ -1,96 +1,98 @@
-import gleam/base
-import gleam/bit_string.{BitString}
-import gleam/io
-import gleam/list
-import gleam/should
-
-external fn list_to_binary(List(Int)) -> BitString =
- "erlang" "list_to_binary"
-
-pub fn encode64_test() {
- [255, 127, 254, 252]
- |> list_to_binary()
- |> base.encode64(True)
- |> should.equal("/3/+/A==")
-
- [255, 127, 254, 252]
- |> list_to_binary()
- |> base.encode64(False)
- |> should.equal("/3/+/A")
-
- [0, 0, 0]
- |> list_to_binary()
- |> base.encode64(True)
- |> should.equal("AAAA")
-
- []
- |> list_to_binary()
- |> base.encode64(True)
- |> should.equal("")
-}
-
-pub fn decode64_test() {
- "/3/+/A=="
- |> base.decode64()
- |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
-
- "/3/+/A"
- |> base.decode64()
- |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
-
- "AAAA"
- |> base.decode64()
- |> should.equal(Ok(list_to_binary([0, 0, 0])))
-
- ""
- |> base.decode64()
- |> should.equal(Ok(list_to_binary([])))
-
- ")!"
- |> base.decode64()
- |> should.equal(Error(Nil))
-}
-
-pub fn url_encode64_test() {
- [255, 127, 254, 252]
- |> list_to_binary()
- |> base.url_encode64(True)
- |> should.equal("_3_-_A==")
-
- [255, 127, 254, 252]
- |> list_to_binary()
- |> base.url_encode64(False)
- |> should.equal("_3_-_A")
-
- [0, 0, 0]
- |> list_to_binary()
- |> base.url_encode64(True)
- |> should.equal("AAAA")
-
- []
- |> list_to_binary()
- |> base.url_encode64(True)
- |> should.equal("")
-}
-
-pub fn url_decode64_test() {
- "_3_-_A=="
- |> base.url_decode64()
- |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
-
- "_3_-_A"
- |> base.url_decode64()
- |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
-
- "AAAA"
- |> base.url_decode64()
- |> should.equal(Ok(list_to_binary([0, 0, 0])))
-
- ""
- |> base.url_decode64()
- |> should.equal(Ok(list_to_binary([])))
-
- ")!"
- |> base.url_decode64()
- |> should.equal(Error(Nil))
+if erlang {
+ import gleam/base
+ import gleam/bit_string.{BitString}
+ import gleam/io
+ import gleam/list
+ import gleam/should
+
+ external fn list_to_binary(List(Int)) -> BitString =
+ "erlang" "list_to_binary"
+
+ pub fn encode64_test() {
+ [255, 127, 254, 252]
+ |> list_to_binary()
+ |> base.encode64(True)
+ |> should.equal("/3/+/A==")
+
+ [255, 127, 254, 252]
+ |> list_to_binary()
+ |> base.encode64(False)
+ |> should.equal("/3/+/A")
+
+ [0, 0, 0]
+ |> list_to_binary()
+ |> base.encode64(True)
+ |> should.equal("AAAA")
+
+ []
+ |> list_to_binary()
+ |> base.encode64(True)
+ |> should.equal("")
+ }
+
+ pub fn decode64_test() {
+ "/3/+/A=="
+ |> base.decode64()
+ |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
+
+ "/3/+/A"
+ |> base.decode64()
+ |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
+
+ "AAAA"
+ |> base.decode64()
+ |> should.equal(Ok(list_to_binary([0, 0, 0])))
+
+ ""
+ |> base.decode64()
+ |> should.equal(Ok(list_to_binary([])))
+
+ ")!"
+ |> base.decode64()
+ |> should.equal(Error(Nil))
+ }
+
+ pub fn url_encode64_test() {
+ [255, 127, 254, 252]
+ |> list_to_binary()
+ |> base.url_encode64(True)
+ |> should.equal("_3_-_A==")
+
+ [255, 127, 254, 252]
+ |> list_to_binary()
+ |> base.url_encode64(False)
+ |> should.equal("_3_-_A")
+
+ [0, 0, 0]
+ |> list_to_binary()
+ |> base.url_encode64(True)
+ |> should.equal("AAAA")
+
+ []
+ |> list_to_binary()
+ |> base.url_encode64(True)
+ |> should.equal("")
+ }
+
+ pub fn url_decode64_test() {
+ "_3_-_A=="
+ |> base.url_decode64()
+ |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
+
+ "_3_-_A"
+ |> base.url_decode64()
+ |> should.equal(Ok(list_to_binary([255, 127, 254, 252])))
+
+ "AAAA"
+ |> base.url_decode64()
+ |> should.equal(Ok(list_to_binary([0, 0, 0])))
+
+ ""
+ |> base.url_decode64()
+ |> should.equal(Ok(list_to_binary([])))
+
+ ")!"
+ |> base.url_decode64()
+ |> should.equal(Error(Nil))
+ }
}
diff --git a/test/gleam/bit_builder_test.gleam b/test/gleam/bit_builder_test.gleam
index e1ec57b..fac962f 100644
--- a/test/gleam/bit_builder_test.gleam
+++ b/test/gleam/bit_builder_test.gleam
@@ -1,75 +1,77 @@
-import gleam/should
-import gleam/bit_builder
+if erlang {
+ import gleam/should
+ import gleam/bit_builder
-pub fn builder_test() {
- let data =
- bit_builder.from_bit_string(<<1>>)
- |> bit_builder.append(<<2>>)
- |> bit_builder.append(<<3>>)
- |> bit_builder.prepend(<<0>>)
+ pub fn builder_test() {
+ let data =
+ bit_builder.from_bit_string(<<1>>)
+ |> bit_builder.append(<<2>>)
+ |> bit_builder.append(<<3>>)
+ |> bit_builder.prepend(<<0>>)
- data
- |> bit_builder.to_bit_string
- |> should.equal(<<0, 1, 2, 3>>)
+ data
+ |> bit_builder.to_bit_string
+ |> should.equal(<<0, 1, 2, 3>>)
- data
- |> bit_builder.byte_size
- |> should.equal(4)
-}
+ data
+ |> bit_builder.byte_size
+ |> should.equal(4)
+ }
-pub fn builder_with_strings_test() {
- let data =
- bit_builder.from_bit_string(<<1>>)
- |> bit_builder.append_string("2")
- |> bit_builder.append_string("3")
- |> bit_builder.prepend_string("0")
+ pub fn builder_with_strings_test() {
+ let data =
+ bit_builder.from_bit_string(<<1>>)
+ |> bit_builder.append_string("2")
+ |> bit_builder.append_string("3")
+ |> bit_builder.prepend_string("0")
- data
- |> bit_builder.to_bit_string
- |> should.equal(<<"0":utf8, 1, "2":utf8, "3":utf8>>)
+ data
+ |> bit_builder.to_bit_string
+ |> should.equal(<<"0":utf8, 1, "2":utf8, "3":utf8>>)
- data
- |> bit_builder.byte_size
- |> should.equal(4)
-}
+ data
+ |> bit_builder.byte_size
+ |> should.equal(4)
+ }
-pub fn builder_with_builders_test() {
- let data =
- bit_builder.from_bit_string(<<1>>)
- |> bit_builder.append_builder(bit_builder.from_bit_string(<<2>>))
- |> bit_builder.append_builder(bit_builder.from_bit_string(<<3>>))
- |> bit_builder.prepend_builder(bit_builder.from_bit_string(<<0>>))
+ pub fn builder_with_builders_test() {
+ let data =
+ bit_builder.from_bit_string(<<1>>)
+ |> bit_builder.append_builder(bit_builder.from_bit_string(<<2>>))
+ |> bit_builder.append_builder(bit_builder.from_bit_string(<<3>>))
+ |> bit_builder.prepend_builder(bit_builder.from_bit_string(<<0>>))
- data
- |> bit_builder.to_bit_string
- |> should.equal(<<0, 1, 2, 3>>)
+ data
+ |> bit_builder.to_bit_string
+ |> should.equal(<<0, 1, 2, 3>>)
- data
- |> bit_builder.byte_size
- |> should.equal(4)
-}
+ data
+ |> bit_builder.byte_size
+ |> should.equal(4)
+ }
-pub fn concat_test() {
- [
- bit_builder.from_bit_string(<<1, 2>>),
- bit_builder.from_bit_string(<<3, 4>>),
- bit_builder.from_bit_string(<<5, 6>>),
- ]
- |> bit_builder.concat
- |> bit_builder.to_bit_string
- |> should.equal(<<1, 2, 3, 4, 5, 6>>)
-}
+ pub fn concat_test() {
+ [
+ bit_builder.from_bit_string(<<1, 2>>),
+ bit_builder.from_bit_string(<<3, 4>>),
+ bit_builder.from_bit_string(<<5, 6>>),
+ ]
+ |> bit_builder.concat
+ |> bit_builder.to_bit_string
+ |> should.equal(<<1, 2, 3, 4, 5, 6>>)
+ }
-pub fn from_bit_string_test() {
- // Regression test: no additional modification of the builder
- bit_builder.from_bit_string(<<>>)
- |> bit_builder.to_bit_string
- |> should.equal(<<>>)
-}
+ pub fn from_bit_string_test() {
+ // Regression test: no additional modification of the builder
+ bit_builder.from_bit_string(<<>>)
+ |> bit_builder.to_bit_string
+ |> should.equal(<<>>)
+ }
-pub fn from_string_test() {
- // Regression test: no additional modification of the builder
- bit_builder.from_string("")
- |> bit_builder.to_bit_string
- |> should.equal(<<>>)
+ pub fn from_string_test() {
+ // Regression test: no additional modification of the builder
+ bit_builder.from_string("")
+ |> bit_builder.to_bit_string
+ |> should.equal(<<>>)
+ }
}
diff --git a/test/gleam/bit_string_test.gleam b/test/gleam/bit_string_test.gleam
index ea577fd..a69bc90 100644
--- a/test/gleam/bit_string_test.gleam
+++ b/test/gleam/bit_string_test.gleam
@@ -1,93 +1,98 @@
-import gleam/bit_string
-import gleam/should
-
-pub fn length_test() {
- bit_string.byte_size(bit_string.from_string("hello"))
- |> should.equal(5)
-
- bit_string.byte_size(bit_string.from_string(""))
- |> should.equal(0)
-}
-
-pub fn append_test() {
- bit_string.from_string("Test")
- |> bit_string.append(bit_string.from_string(" Me"))
- |> should.equal(bit_string.from_string("Test Me"))
-
- let Ok(zero_32bit) = bit_string.int_to_u32(0)
- zero_32bit
- |> bit_string.append(bit_string.from_string(""))
- |> should.equal(zero_32bit)
-}
-
-pub fn part_test() {
- bit_string.from_string("hello")
- |> bit_string.part(0, 5)
- |> should.equal(Ok(bit_string.from_string("hello")))
-
- bit_string.from_string("hello")
- |> bit_string.part(0, 0)
- |> should.equal(Ok(bit_string.from_string("")))
-
- bit_string.from_string("hello")
- |> bit_string.part(2, 2)
- |> should.equal(Ok(bit_string.from_string("ll")))
-
- bit_string.from_string("hello")
- |> bit_string.part(5, -2)
- |> should.equal(Ok(bit_string.from_string("lo")))
-
- bit_string.from_string("")
- |> bit_string.part(0, 0)
- |> should.equal(Ok(bit_string.from_string("")))
-
- bit_string.from_string("hello")
- |> bit_string.part(6, 0)
- |> should.equal(Error(Nil))
-
- bit_string.from_string("hello")
- |> bit_string.part(-1, 1)
- |> should.equal(Error(Nil))
-
- bit_string.from_string("hello")
- |> bit_string.part(1, 6)
- |> should.equal(Error(Nil))
-}
-
-pub fn u32_test() {
- let Ok(bin) = bit_string.int_to_u32(0)
- should.equal(4, bit_string.byte_size(bin))
- should.equal(Ok(0), bit_string.int_from_u32(bin))
-
- let Ok(bin) = bit_string.int_to_u32(4294967295)
- should.equal(4, bit_string.byte_size(bin))
- should.equal(Ok(4294967295), bit_string.int_from_u32(bin))
-
- should.equal(Error(Nil), bit_string.int_from_u32(bit_string.from_string("")))
- should.equal(
- Error(Nil),
- bit_string.int_from_u32(bit_string.from_string("12345")),
- )
-}
-
-pub fn to_string_test() {
- <<>>
- |> bit_string.to_string
- |> should.equal(Ok(""))
-
- <<"":utf8>>
- |> bit_string.to_string
- |> should.equal(Ok(""))
-
- <<"Hello":utf8>>
- |> bit_string.to_string
- |> should.equal(Ok("Hello"))
-
- <<"ø":utf8>>
- |> bit_string.to_string
- |> should.equal(Ok("ø"))
-
- <<65535:16>>
- |> bit_string.to_string
- |> should.equal(Error(Nil))
+if erlang {
+ import gleam/bit_string
+ import gleam/should
+
+ pub fn length_test() {
+ bit_string.byte_size(bit_string.from_string("hello"))
+ |> should.equal(5)
+
+ bit_string.byte_size(bit_string.from_string(""))
+ |> should.equal(0)
+ }
+
+ pub fn append_test() {
+ bit_string.from_string("Test")
+ |> bit_string.append(bit_string.from_string(" Me"))
+ |> should.equal(bit_string.from_string("Test Me"))
+
+ let Ok(zero_32bit) = bit_string.int_to_u32(0)
+ zero_32bit
+ |> bit_string.append(bit_string.from_string(""))
+ |> should.equal(zero_32bit)
+ }
+
+ pub fn part_test() {
+ bit_string.from_string("hello")
+ |> bit_string.part(0, 5)
+ |> should.equal(Ok(bit_string.from_string("hello")))
+
+ bit_string.from_string("hello")
+ |> bit_string.part(0, 0)
+ |> should.equal(Ok(bit_string.from_string("")))
+
+ bit_string.from_string("hello")
+ |> bit_string.part(2, 2)
+ |> should.equal(Ok(bit_string.from_string("ll")))
+
+ bit_string.from_string("hello")
+ |> bit_string.part(5, -2)
+ |> should.equal(Ok(bit_string.from_string("lo")))
+
+ bit_string.from_string("")
+ |> bit_string.part(0, 0)
+ |> should.equal(Ok(bit_string.from_string("")))
+
+ bit_string.from_string("hello")
+ |> bit_string.part(6, 0)
+ |> should.equal(Error(Nil))
+
+ bit_string.from_string("hello")
+ |> bit_string.part(-1, 1)
+ |> should.equal(Error(Nil))
+
+ bit_string.from_string("hello")
+ |> bit_string.part(1, 6)
+ |> should.equal(Error(Nil))
+ }
+
+ pub fn u32_test() {
+ let Ok(bin) = bit_string.int_to_u32(0)
+ should.equal(4, bit_string.byte_size(bin))
+ should.equal(Ok(0), bit_string.int_from_u32(bin))
+
+ let Ok(bin) = bit_string.int_to_u32(4294967295)
+ should.equal(4, bit_string.byte_size(bin))
+ should.equal(Ok(4294967295), bit_string.int_from_u32(bin))
+
+ should.equal(
+ Error(Nil),
+ bit_string.int_from_u32(bit_string.from_string("")),
+ )
+ should.equal(
+ Error(Nil),
+ bit_string.int_from_u32(bit_string.from_string("12345")),
+ )
+ }
+
+ pub fn to_string_test() {
+ <<>>
+ |> bit_string.to_string
+ |> should.equal(Ok(""))
+
+ <<"":utf8>>
+ |> bit_string.to_string
+ |> should.equal(Ok(""))
+
+ <<"Hello":utf8>>
+ |> bit_string.to_string
+ |> should.equal(Ok("Hello"))
+
+ <<"ø":utf8>>
+ |> bit_string.to_string
+ |> should.equal(Ok("ø"))
+
+ <<65535:16>>
+ |> bit_string.to_string
+ |> should.equal(Error(Nil))
+ }
}
diff --git a/test/gleam/bool_test.gleam b/test/gleam/bool_test.gleam
index 3edea25..9658377 100644
--- a/test/gleam/bool_test.gleam
+++ b/test/gleam/bool_test.gleam
@@ -1,117 +1,119 @@
-import gleam/bool
-import gleam/order
-import gleam/should
+if erlang {
+ import gleam/bool
+ import gleam/order
+ import gleam/should
-pub fn negate_test() {
- bool.negate(True)
- |> should.be_false
+ pub fn negate_test() {
+ bool.negate(True)
+ |> should.be_false
- bool.negate(False)
- |> should.be_true
-}
+ bool.negate(False)
+ |> should.be_true
+ }
-pub fn nor_test() {
- bool.nor(False, False)
- |> should.be_true
+ pub fn nor_test() {
+ bool.nor(False, False)
+ |> should.be_true
- bool.nor(False, True)
- |> should.be_false
+ bool.nor(False, True)
+ |> should.be_false
- bool.nor(True, False)
- |> should.be_false
+ bool.nor(True, False)
+ |> should.be_false
- bool.nor(True, True)
- |> should.be_false
-}
+ bool.nor(True, True)
+ |> should.be_false
+ }
-pub fn nand_test() {
- bool.nand(False, False)
- |> should.be_true
+ pub fn nand_test() {
+ bool.nand(False, False)
+ |> should.be_true
- bool.nand(False, True)
- |> should.be_true
+ bool.nand(False, True)
+ |> should.be_true
- bool.nand(True, False)
- |> should.be_true
+ bool.nand(True, False)
+ |> should.be_true
- bool.nand(True, True)
- |> should.be_false
-}
+ bool.nand(True, True)
+ |> should.be_false
+ }
-pub fn exclusive_or_test() {
- bool.exclusive_or(True, True)
- |> should.be_false
+ pub fn exclusive_or_test() {
+ bool.exclusive_or(True, True)
+ |> should.be_false
- bool.exclusive_or(False, False)
- |> should.be_false
+ bool.exclusive_or(False, False)
+ |> should.be_false
- bool.exclusive_or(True, False)
- |> should.be_true
+ bool.exclusive_or(True, False)
+ |> should.be_true
- bool.exclusive_or(False, True)
- |> should.be_true
-}
+ bool.exclusive_or(False, True)
+ |> should.be_true
+ }
-pub fn exclusive_nor_test() {
- bool.exclusive_nor(False, False)
- |> should.be_true
+ pub fn exclusive_nor_test() {
+ bool.exclusive_nor(False, False)
+ |> should.be_true
- bool.exclusive_nor(False, True)
- |> should.be_false
+ bool.exclusive_nor(False, True)
+ |> should.be_false
- bool.exclusive_nor(True, False)
- |> should.be_false
+ bool.exclusive_nor(True, False)
+ |> should.be_false
- bool.exclusive_nor(True, True)
- |> should.be_true
-}
+ bool.exclusive_nor(True, True)
+ |> should.be_true
+ }
-pub fn compare_test() {
- bool.compare(True, True)
- |> should.equal(order.Eq)
+ pub fn compare_test() {
+ bool.compare(True, True)
+ |> should.equal(order.Eq)
- bool.compare(True, False)
- |> should.equal(order.Gt)
+ bool.compare(True, False)
+ |> should.equal(order.Gt)
- bool.compare(False, False)
- |> should.equal(order.Eq)
+ bool.compare(False, False)
+ |> should.equal(order.Eq)
- bool.compare(False, True)
- |> should.equal(order.Lt)
-}
+ bool.compare(False, True)
+ |> should.equal(order.Lt)
+ }
-pub fn max_test() {
- bool.max(True, True)
- |> should.equal(True)
+ pub fn max_test() {
+ bool.max(True, True)
+ |> should.equal(True)
- bool.max(True, False)
- |> should.equal(True)
+ bool.max(True, False)
+ |> should.equal(True)
- bool.max(False, False)
- |> should.equal(False)
+ bool.max(False, False)
+ |> should.equal(False)
- bool.max(False, True)
- |> should.equal(True)
-}
+ bool.max(False, True)
+ |> should.equal(True)
+ }
-pub fn min_test() {
- bool.min(True, True)
- |> should.equal(True)
+ pub fn min_test() {
+ bool.min(True, True)
+ |> should.equal(True)
- bool.min(True, False)
- |> should.equal(False)
+ bool.min(True, False)
+ |> should.equal(False)
- bool.min(False, False)
- |> should.equal(False)
+ bool.min(False, False)
+ |> should.equal(False)
- bool.min(False, True)
- |> should.equal(False)
-}
+ bool.min(False, True)
+ |> should.equal(False)
+ }
-pub fn to_int_test() {
- bool.to_int(True)
- |> should.equal(1)
+ pub fn to_int_test() {
+ bool.to_int(True)
+ |> should.equal(1)
- bool.to_int(False)
- |> should.equal(0)
+ bool.to_int(False)
+ |> should.equal(0)
+ }
}
diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam
index 2cc82b1..ca82802 100644
--- a/test/gleam/dynamic_test.gleam
+++ b/test/gleam/dynamic_test.gleam
@@ -1,744 +1,746 @@
-import gleam/bit_string
-import gleam/dynamic
-import gleam/atom
-import gleam/list
-import gleam/should
-import gleam/result
-import gleam/map
-import gleam/option.{None, Some}
-
-pub fn bit_string_test() {
- ""
- |> dynamic.from
- |> dynamic.bit_string
- |> should.equal(Ok(<<"":utf8>>))
-
- "Hello"
- |> dynamic.from
- |> dynamic.bit_string
- |> should.equal(Ok(<<"Hello":utf8>>))
-
- <<65535:16>>
- |> dynamic.from
- |> dynamic.bit_string
- |> should.equal(Ok(<<65535:16>>))
-
- 1
- |> dynamic.from
- |> dynamic.bit_string
- |> should.equal(Error("Expected a bit_string, got an int"))
-
- []
- |> dynamic.from
- |> dynamic.bit_string
- |> should.equal(Error("Expected a bit_string, got a list"))
-}
-
-pub fn string_test() {
- ""
- |> dynamic.from
- |> dynamic.string
- |> should.equal(Ok(""))
-
- "Hello"
- |> dynamic.from
- |> dynamic.string
- |> should.equal(Ok("Hello"))
-
- <<65535:16>>
- |> dynamic.from
- |> dynamic.string
- |> should.equal(Error("Expected a string, got a bit_string"))
-
- 1
- |> dynamic.from
- |> dynamic.string
- |> should.equal(Error("Expected a bit_string, got an int"))
-
- []
- |> dynamic.from
- |> dynamic.string
- |> should.equal(Error("Expected a bit_string, got a list"))
-}
-
-pub fn int_test() {
- 1
- |> dynamic.from
- |> dynamic.int
- |> should.equal(Ok(1))
-
- 2
- |> dynamic.from
- |> dynamic.int
- |> should.equal(Ok(2))
-
- 1.0
- |> dynamic.from
- |> dynamic.int
- |> should.equal(Error("Expected an int, got a float"))
-
- []
- |> dynamic.from
- |> dynamic.int
- |> should.equal(Error("Expected an int, got a list"))
-}
-
-pub fn float_test() {
- 1.0
- |> dynamic.from
- |> dynamic.float
- |> should.equal(Ok(1.0))
-
- 2.2
- |> dynamic.from
- |> dynamic.float
- |> should.equal(Ok(2.2))
-
- 1
- |> dynamic.from
- |> dynamic.float
- |> should.equal(Error("Expected a float, got an int"))
-
- []
- |> dynamic.from
- |> dynamic.float
- |> should.equal(Error("Expected a float, got a list"))
-}
-
-pub fn thunk_test() {
- fn() { 1 }
- |> dynamic.from
- |> dynamic.thunk
- |> should.be_ok
-
- fn() { 1 }
- |> dynamic.from
- |> dynamic.thunk
- |> result.map(fn(f) { f() })
- |> should.equal(Ok(dynamic.from(1)))
-
- fn(x) { x }
- |> dynamic.from
- |> dynamic.thunk
- |> should.be_error
-
- 1
- |> dynamic.from
- |> dynamic.thunk
- |> should.be_error
-
- []
- |> dynamic.from
- |> dynamic.thunk
- |> should.be_error
-}
-
-pub fn bool_test() {
- True
- |> dynamic.from
- |> dynamic.bool
- |> should.equal(Ok(True))
-
- False
- |> dynamic.from
- |> dynamic.bool
- |> should.equal(Ok(False))
-
- 1
- |> dynamic.from
- |> dynamic.bool
- |> should.equal(Error("Expected a bool, got an int"))
-
- []
- |> dynamic.from
- |> dynamic.bool
- |> should.equal(Error("Expected a bool, got a list"))
-}
-
-pub fn atom_test() {
- ""
- |> atom.create_from_string
- |> dynamic.from
- |> dynamic.atom
- |> should.equal(Ok(atom.create_from_string("")))
-
- "ok"
- |> atom.create_from_string
- |> dynamic.from
- |> dynamic.atom
- |> should.equal(Ok(atom.create_from_string("ok")))
-
- 1
- |> dynamic.from
- |> dynamic.atom
- |> should.be_error
-
- []
- |> dynamic.from
- |> dynamic.atom
- |> should.be_error
-}
-
-pub fn typed_list_test() {
- []
- |> dynamic.from
- |> dynamic.typed_list(dynamic.string)
- |> should.equal(Ok([]))
-
- []
- |> dynamic.from
- |> dynamic.typed_list(dynamic.int)
- |> should.equal(Ok([]))
-
- [1, 2, 3]
- |> dynamic.from
- |> dynamic.typed_list(dynamic.int)
- |> should.equal(Ok([1, 2, 3]))
-
- [[1], [2], [3]]
- |> dynamic.from
- |> dynamic.typed_list(dynamic.typed_list(_, dynamic.int))
- |> should.equal(Ok([[1], [2], [3]]))
-
- 1
- |> dynamic.from
- |> dynamic.typed_list(dynamic.string)
- |> should.be_error
-
- 1.0
- |> dynamic.from
- |> dynamic.typed_list(dynamic.int)
- |> should.be_error
-
- [""]
- |> dynamic.from
- |> dynamic.typed_list(dynamic.int)
- |> should.be_error
-
- [dynamic.from(1), dynamic.from("not an int")]
- |> dynamic.from
- |> dynamic.typed_list(dynamic.int)
- |> should.be_error
-}
-
-pub fn option_test() {
- let Ok(null) = atom.from_string("null")
-
- 1
- |> dynamic.from
- |> dynamic.option(dynamic.int)
- |> should.equal(Ok(Some(1)))
- null
- |> dynamic.from
- |> dynamic.option(dynamic.int)
- |> should.equal(Ok(None))
- 1
- |> dynamic.from
- |> dynamic.option(dynamic.string)
- |> should.be_error
-}
-
-pub fn field_test() {
- let Ok(ok_atom) = atom.from_string("ok")
- let Ok(error_atom) = atom.from_string("error")
-
- map.new()
- |> map.insert(ok_atom, 1)
- |> dynamic.from
- |> dynamic.field(ok_atom)
- |> should.equal(Ok(dynamic.from(1)))
-
- map.new()
- |> map.insert(ok_atom, 3)
- |> map.insert(error_atom, 1)
- |> dynamic.from
- |> dynamic.field(ok_atom)
- |> should.equal(Ok(dynamic.from(3)))
-
- map.new()
- |> dynamic.from
- |> dynamic.field(ok_atom)
- |> should.be_error
-
- 1
- |> dynamic.from
- |> dynamic.field(ok_atom)
- |> should.be_error
-
- []
- |> dynamic.from
- |> dynamic.field([])
- |> should.be_error
-}
-
-pub fn element_test() {
- let Ok(ok_atom) = atom.from_string("ok")
- let ok_one_tuple = #(ok_atom, 1)
-
- ok_one_tuple
- |> dynamic.from
- |> dynamic.element(0)
- |> should.equal(Ok(dynamic.from(ok_atom)))
-
- ok_one_tuple
- |> dynamic.from
- |> dynamic.element(1)
- |> should.equal(Ok(dynamic.from(1)))
-
- ok_one_tuple
- |> dynamic.from
- |> dynamic.element(2)
- |> should.be_error
-
- ok_one_tuple
- |> dynamic.from
- |> dynamic.element(-1)
- |> should.be_error
-
- 1
- |> dynamic.from
- |> dynamic.element(0)
- |> should.be_error
-
- map.new()
- |> map.insert(1, ok_atom)
- |> dynamic.from
- |> dynamic.element(0)
- |> should.be_error
-}
-
-pub fn tuple2_test() {
- #(1, 2)
- |> dynamic.from
- |> dynamic.tuple2
- |> should.equal(Ok(#(dynamic.from(1), dynamic.from(2))))
-
- #(1, "")
- |> dynamic.from
- |> dynamic.tuple2
- |> should.equal(Ok(#(dynamic.from(1), dynamic.from(""))))
-
- #(1, 2, 3)
- |> dynamic.from
- |> dynamic.tuple2
- |> should.equal(Error("Expected a 2 element tuple, got a 3 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.tuple2
- |> should.equal(Error("Expected a 2 element tuple, got an int"))
-}
-
-pub fn typed_tuple2_test() {
- #(1, 2)
- |> dynamic.from
- |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
- |> should.equal(Ok(#(1, 2)))
-
- #(1, "")
- |> dynamic.from
- |> dynamic.typed_tuple2(dynamic.int, dynamic.string)
- |> should.equal(Ok(#(1, "")))
-
- #(1, "")
- |> dynamic.from
- |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
- |> should.equal(Error("Expected an int, got a binary"))
-
- #(1, 2, 3)
- |> dynamic.from
- |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
- |> should.equal(Error("Expected a 2 element tuple, got a 3 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
- |> should.equal(Error("Expected a 2 element tuple, got an int"))
-}
-
-pub fn tuple3_test() {
- #(1, 2, 3)
- |> dynamic.from
- |> dynamic.tuple3
- |> should.equal(Ok(#(dynamic.from(1), dynamic.from(2), dynamic.from(3))))
-
- #(1, "", 3.0)
- |> dynamic.from
- |> dynamic.tuple3
- |> should.equal(Ok(#(dynamic.from(1), dynamic.from(""), dynamic.from(3.0))))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.tuple3
- |> should.equal(Error("Expected a 3 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.tuple3
- |> should.equal(Error("Expected a 3 element tuple, got an int"))
-}
-
-pub fn typed_tuple3_test() {
- #(1, 2, 3)
- |> dynamic.from
- |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Ok(#(1, 2, 3)))
-
- #(1, "", 3.0)
- |> dynamic.from
- |> dynamic.typed_tuple3(dynamic.int, dynamic.string, dynamic.float)
- |> should.equal(Ok(#(1, "", 3.0)))
-
- #(1, 2, "")
- |> dynamic.from
- |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Error("Expected an int, got a binary"))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Error("Expected a 3 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Error("Expected a 3 element tuple, got an int"))
-}
-
-pub fn tuple4_test() {
- #(1, 2, 3, 4)
- |> dynamic.from
- |> dynamic.tuple4
- |> should.equal(Ok(#(
- dynamic.from(1),
- dynamic.from(2),
- dynamic.from(3),
- dynamic.from(4),
- )))
-
- #(1, "", 3.0, 4)
- |> dynamic.from
- |> dynamic.tuple4
- |> should.equal(Ok(#(
- dynamic.from(1),
- dynamic.from(""),
- dynamic.from(3.0),
- dynamic.from(4),
- )))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.tuple4
- |> should.equal(Error("Expected a 4 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.tuple4
- |> should.equal(Error("Expected a 4 element tuple, got an int"))
-}
-
-pub fn typed_tuple4_test() {
- #(1, 2, 3, 4)
- |> dynamic.from
- |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Ok(#(1, 2, 3, 4)))
-
- #(1, "", 3.0, 4)
- |> dynamic.from
- |> dynamic.typed_tuple4(
- dynamic.int,
- dynamic.string,
- dynamic.float,
- dynamic.int,
- )
- |> should.equal(Ok(#(1, "", 3.0, 4)))
-
- #(1, 2, 3, "")
- |> dynamic.from
- |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Error("Expected an int, got a binary"))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Error("Expected a 4 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
- |> should.equal(Error("Expected a 4 element tuple, got an int"))
-}
-
-pub fn tuple5_test() {
- #(1, 2, 3, 4, 5)
- |> dynamic.from
- |> dynamic.tuple5
- |> should.equal(Ok(#(
- dynamic.from(1),
- dynamic.from(2),
- dynamic.from(3),
- dynamic.from(4),
- dynamic.from(5),
- )))
-
- #(1, "", 3.0, 4, 5)
- |> dynamic.from
- |> dynamic.tuple5
- |> should.equal(Ok(#(
- dynamic.from(1),
- dynamic.from(""),
- dynamic.from(3.0),
- dynamic.from(4),
- dynamic.from(5),
- )))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.tuple5
- |> should.equal(Error("Expected a 5 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.tuple5
- |> should.equal(Error("Expected a 5 element tuple, got an int"))
-}
-
-pub fn typed_tuple5_test() {
- #(1, 2, 3, 4, 5)
- |> dynamic.from
- |> dynamic.typed_tuple5(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Ok(#(1, 2, 3, 4, 5)))
-
- #(1, "", 3.0, 4, 5)
- |> dynamic.from
- |> dynamic.typed_tuple5(
- dynamic.int,
- dynamic.string,
- dynamic.float,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Ok(#(1, "", 3.0, 4, 5)))
-
- #(1, 2, 3, 4, "")
- |> dynamic.from
- |> dynamic.typed_tuple5(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Error("Expected an int, got a binary"))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.typed_tuple5(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Error("Expected a 5 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.typed_tuple5(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Error("Expected a 5 element tuple, got an int"))
-}
-
-pub fn tuple6_test() {
- #(1, 2, 3, 4, 5, 6)
- |> dynamic.from
- |> dynamic.tuple6
- |> should.equal(Ok(#(
- dynamic.from(1),
- dynamic.from(2),
- dynamic.from(3),
- dynamic.from(4),
- dynamic.from(5),
- dynamic.from(6),
- )))
-
- #(1, "", 3.0, 4, 5, 6)
- |> dynamic.from
- |> dynamic.tuple6
- |> should.equal(Ok(#(
- dynamic.from(1),
- dynamic.from(""),
- dynamic.from(3.0),
- dynamic.from(4),
- dynamic.from(5),
- dynamic.from(6),
- )))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.tuple6
- |> should.equal(Error("Expected a 6 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.tuple6
- |> should.equal(Error("Expected a 6 element tuple, got an int"))
-}
-
-pub fn typed_tuple6_test() {
- #(1, 2, 3, 4, 5, 6)
- |> dynamic.from
- |> dynamic.typed_tuple6(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Ok(#(1, 2, 3, 4, 5, 6)))
-
- #(1, "", 3.0, 4, 5, 6)
- |> dynamic.from
- |> dynamic.typed_tuple6(
- dynamic.int,
- dynamic.string,
- dynamic.float,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Ok(#(1, "", 3.0, 4, 5, 6)))
-
- #(1, 2, 3, 4, 5, "")
- |> dynamic.from
- |> dynamic.typed_tuple6(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Error("Expected an int, got a binary"))
-
- #(1, 2)
- |> dynamic.from
- |> dynamic.typed_tuple6(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Error("Expected a 6 element tuple, got a 2 element tuple"))
-
- 1
- |> dynamic.from
- |> dynamic.typed_tuple6(
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- dynamic.int,
- )
- |> should.equal(Error("Expected a 6 element tuple, got an int"))
-}
-
-pub fn map_test() {
- map.new()
- |> dynamic.from
- |> dynamic.map
- |> should.equal(Ok(map.new()))
-
- 1
- |> dynamic.from
- |> dynamic.map
- |> should.equal(Error("Expected a map, got an int"))
-}
-
-pub fn list_test() {
- []
- |> dynamic.from
- |> dynamic.list
- |> should.equal(Ok([]))
-
- [1, 2]
- |> dynamic.from
- |> dynamic.list
- |> should.equal(Ok([dynamic.from(1), dynamic.from(2)]))
-
- [dynamic.from(1), dynamic.from(2.0)]
- |> dynamic.from
- |> dynamic.list
- |> should.equal(Ok([dynamic.from(1), dynamic.from(2.0)]))
-
- 1
- |> dynamic.from
- |> dynamic.list
- |> should.equal(Error("Expected a list, got an int"))
-}
-
-pub fn result_test() {
- Ok(1)
- |> dynamic.from
- |> dynamic.result
- |> should.equal(Ok(Ok(dynamic.from(1))))
-
- Error("error")
- |> dynamic.from
- |> dynamic.result
- |> should.equal(Ok(Error(dynamic.from("error"))))
-
- 1
- |> dynamic.from
- |> dynamic.result
- |> should.equal(Error("Expected a 2 element tuple, got an int"))
-
- let tag = atom.create_from_string("bad")
-
- #(tag, "value")
- |> dynamic.from
- |> dynamic.result
- |> should.equal(Error("Expected a tag of \"ok\" or \"error\", got \"bad\""))
-}
-
-pub fn typed_result_test() {
- Ok(1)
- |> dynamic.from
- |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
- |> should.equal(Ok(Ok(1)))
-
- Error("error")
- |> dynamic.from
- |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
- |> should.equal(Ok(Error("error")))
-
- Ok("1")
- |> dynamic.from
- |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
- |> should.equal(Error("Expected an int, got a binary"))
-
- Error(1)
- |> dynamic.from
- |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
- |> should.equal(Error("Expected a bit_string, got an int"))
-
- 1
- |> dynamic.from
- |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
- |> should.equal(Error("Expected a 2 element tuple, got an int"))
+if erlang {
+ import gleam/bit_string
+ import gleam/dynamic
+ import gleam/atom
+ import gleam/list
+ import gleam/should
+ import gleam/result
+ import gleam/map
+ import gleam/option.{None, Some}
+
+ pub fn bit_string_test() {
+ ""
+ |> dynamic.from
+ |> dynamic.bit_string
+ |> should.equal(Ok(<<"":utf8>>))
+
+ "Hello"
+ |> dynamic.from
+ |> dynamic.bit_string
+ |> should.equal(Ok(<<"Hello":utf8>>))
+
+ <<65535:16>>
+ |> dynamic.from
+ |> dynamic.bit_string
+ |> should.equal(Ok(<<65535:16>>))
+
+ 1
+ |> dynamic.from
+ |> dynamic.bit_string
+ |> should.equal(Error("Expected a bit_string, got an int"))
+
+ []
+ |> dynamic.from
+ |> dynamic.bit_string
+ |> should.equal(Error("Expected a bit_string, got a list"))
+ }
+
+ pub fn string_test() {
+ ""
+ |> dynamic.from
+ |> dynamic.string
+ |> should.equal(Ok(""))
+
+ "Hello"
+ |> dynamic.from
+ |> dynamic.string
+ |> should.equal(Ok("Hello"))
+
+ <<65535:16>>
+ |> dynamic.from
+ |> dynamic.string
+ |> should.equal(Error("Expected a string, got a bit_string"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.string
+ |> should.equal(Error("Expected a bit_string, got an int"))
+
+ []
+ |> dynamic.from
+ |> dynamic.string
+ |> should.equal(Error("Expected a bit_string, got a list"))
+ }
+
+ pub fn int_test() {
+ 1
+ |> dynamic.from
+ |> dynamic.int
+ |> should.equal(Ok(1))
+
+ 2
+ |> dynamic.from
+ |> dynamic.int
+ |> should.equal(Ok(2))
+
+ 1.0
+ |> dynamic.from
+ |> dynamic.int
+ |> should.equal(Error("Expected an int, got a float"))
+
+ []
+ |> dynamic.from
+ |> dynamic.int
+ |> should.equal(Error("Expected an int, got a list"))
+ }
+
+ pub fn float_test() {
+ 1.0
+ |> dynamic.from
+ |> dynamic.float
+ |> should.equal(Ok(1.0))
+
+ 2.2
+ |> dynamic.from
+ |> dynamic.float
+ |> should.equal(Ok(2.2))
+
+ 1
+ |> dynamic.from
+ |> dynamic.float
+ |> should.equal(Error("Expected a float, got an int"))
+
+ []
+ |> dynamic.from
+ |> dynamic.float
+ |> should.equal(Error("Expected a float, got a list"))
+ }
+
+ pub fn thunk_test() {
+ fn() { 1 }
+ |> dynamic.from
+ |> dynamic.thunk
+ |> should.be_ok
+
+ fn() { 1 }
+ |> dynamic.from
+ |> dynamic.thunk
+ |> result.map(fn(f) { f() })
+ |> should.equal(Ok(dynamic.from(1)))
+
+ fn(x) { x }
+ |> dynamic.from
+ |> dynamic.thunk
+ |> should.be_error
+
+ 1
+ |> dynamic.from
+ |> dynamic.thunk
+ |> should.be_error
+
+ []
+ |> dynamic.from
+ |> dynamic.thunk
+ |> should.be_error
+ }
+
+ pub fn bool_test() {
+ True
+ |> dynamic.from
+ |> dynamic.bool
+ |> should.equal(Ok(True))
+
+ False
+ |> dynamic.from
+ |> dynamic.bool
+ |> should.equal(Ok(False))
+
+ 1
+ |> dynamic.from
+ |> dynamic.bool
+ |> should.equal(Error("Expected a bool, got an int"))
+
+ []
+ |> dynamic.from
+ |> dynamic.bool
+ |> should.equal(Error("Expected a bool, got a list"))
+ }
+
+ pub fn atom_test() {
+ ""
+ |> atom.create_from_string
+ |> dynamic.from
+ |> dynamic.atom
+ |> should.equal(Ok(atom.create_from_string("")))
+
+ "ok"
+ |> atom.create_from_string
+ |> dynamic.from
+ |> dynamic.atom
+ |> should.equal(Ok(atom.create_from_string("ok")))
+
+ 1
+ |> dynamic.from
+ |> dynamic.atom
+ |> should.be_error
+
+ []
+ |> dynamic.from
+ |> dynamic.atom
+ |> should.be_error
+ }
+
+ pub fn typed_list_test() {
+ []
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.string)
+ |> should.equal(Ok([]))
+
+ []
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.int)
+ |> should.equal(Ok([]))
+
+ [1, 2, 3]
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.int)
+ |> should.equal(Ok([1, 2, 3]))
+
+ [[1], [2], [3]]
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.typed_list(_, dynamic.int))
+ |> should.equal(Ok([[1], [2], [3]]))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.string)
+ |> should.be_error
+
+ 1.0
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.int)
+ |> should.be_error
+
+ [""]
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.int)
+ |> should.be_error
+
+ [dynamic.from(1), dynamic.from("not an int")]
+ |> dynamic.from
+ |> dynamic.typed_list(dynamic.int)
+ |> should.be_error
+ }
+
+ pub fn option_test() {
+ let Ok(null) = atom.from_string("null")
+
+ 1
+ |> dynamic.from
+ |> dynamic.option(dynamic.int)
+ |> should.equal(Ok(Some(1)))
+ null
+ |> dynamic.from
+ |> dynamic.option(dynamic.int)
+ |> should.equal(Ok(None))
+ 1
+ |> dynamic.from
+ |> dynamic.option(dynamic.string)
+ |> should.be_error
+ }
+
+ pub fn field_test() {
+ let Ok(ok_atom) = atom.from_string("ok")
+ let Ok(error_atom) = atom.from_string("error")
+
+ map.new()
+ |> map.insert(ok_atom, 1)
+ |> dynamic.from
+ |> dynamic.field(ok_atom)
+ |> should.equal(Ok(dynamic.from(1)))
+
+ map.new()
+ |> map.insert(ok_atom, 3)
+ |> map.insert(error_atom, 1)
+ |> dynamic.from
+ |> dynamic.field(ok_atom)
+ |> should.equal(Ok(dynamic.from(3)))
+
+ map.new()
+ |> dynamic.from
+ |> dynamic.field(ok_atom)
+ |> should.be_error
+
+ 1
+ |> dynamic.from
+ |> dynamic.field(ok_atom)
+ |> should.be_error
+
+ []
+ |> dynamic.from
+ |> dynamic.field([])
+ |> should.be_error
+ }
+
+ pub fn element_test() {
+ let Ok(ok_atom) = atom.from_string("ok")
+ let ok_one_tuple = #(ok_atom, 1)
+
+ ok_one_tuple
+ |> dynamic.from
+ |> dynamic.element(0)
+ |> should.equal(Ok(dynamic.from(ok_atom)))
+
+ ok_one_tuple
+ |> dynamic.from
+ |> dynamic.element(1)
+ |> should.equal(Ok(dynamic.from(1)))
+
+ ok_one_tuple
+ |> dynamic.from
+ |> dynamic.element(2)
+ |> should.be_error
+
+ ok_one_tuple
+ |> dynamic.from
+ |> dynamic.element(-1)
+ |> should.be_error
+
+ 1
+ |> dynamic.from
+ |> dynamic.element(0)
+ |> should.be_error
+
+ map.new()
+ |> map.insert(1, ok_atom)
+ |> dynamic.from
+ |> dynamic.element(0)
+ |> should.be_error
+ }
+
+ pub fn tuple2_test() {
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.tuple2
+ |> should.equal(Ok(#(dynamic.from(1), dynamic.from(2))))
+
+ #(1, "")
+ |> dynamic.from
+ |> dynamic.tuple2
+ |> should.equal(Ok(#(dynamic.from(1), dynamic.from(""))))
+
+ #(1, 2, 3)
+ |> dynamic.from
+ |> dynamic.tuple2
+ |> should.equal(Error("Expected a 2 element tuple, got a 3 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.tuple2
+ |> should.equal(Error("Expected a 2 element tuple, got an int"))
+ }
+
+ pub fn typed_tuple2_test() {
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
+ |> should.equal(Ok(#(1, 2)))
+
+ #(1, "")
+ |> dynamic.from
+ |> dynamic.typed_tuple2(dynamic.int, dynamic.string)
+ |> should.equal(Ok(#(1, "")))
+
+ #(1, "")
+ |> dynamic.from
+ |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected an int, got a binary"))
+
+ #(1, 2, 3)
+ |> dynamic.from
+ |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected a 2 element tuple, got a 3 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_tuple2(dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected a 2 element tuple, got an int"))
+ }
+
+ pub fn tuple3_test() {
+ #(1, 2, 3)
+ |> dynamic.from
+ |> dynamic.tuple3
+ |> should.equal(Ok(#(dynamic.from(1), dynamic.from(2), dynamic.from(3))))
+
+ #(1, "", 3.0)
+ |> dynamic.from
+ |> dynamic.tuple3
+ |> should.equal(Ok(#(dynamic.from(1), dynamic.from(""), dynamic.from(3.0))))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.tuple3
+ |> should.equal(Error("Expected a 3 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.tuple3
+ |> should.equal(Error("Expected a 3 element tuple, got an int"))
+ }
+
+ pub fn typed_tuple3_test() {
+ #(1, 2, 3)
+ |> dynamic.from
+ |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Ok(#(1, 2, 3)))
+
+ #(1, "", 3.0)
+ |> dynamic.from
+ |> dynamic.typed_tuple3(dynamic.int, dynamic.string, dynamic.float)
+ |> should.equal(Ok(#(1, "", 3.0)))
+
+ #(1, 2, "")
+ |> dynamic.from
+ |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected an int, got a binary"))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected a 3 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_tuple3(dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected a 3 element tuple, got an int"))
+ }
+
+ pub fn tuple4_test() {
+ #(1, 2, 3, 4)
+ |> dynamic.from
+ |> dynamic.tuple4
+ |> should.equal(Ok(#(
+ dynamic.from(1),
+ dynamic.from(2),
+ dynamic.from(3),
+ dynamic.from(4),
+ )))
+
+ #(1, "", 3.0, 4)
+ |> dynamic.from
+ |> dynamic.tuple4
+ |> should.equal(Ok(#(
+ dynamic.from(1),
+ dynamic.from(""),
+ dynamic.from(3.0),
+ dynamic.from(4),
+ )))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.tuple4
+ |> should.equal(Error("Expected a 4 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.tuple4
+ |> should.equal(Error("Expected a 4 element tuple, got an int"))
+ }
+
+ pub fn typed_tuple4_test() {
+ #(1, 2, 3, 4)
+ |> dynamic.from
+ |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Ok(#(1, 2, 3, 4)))
+
+ #(1, "", 3.0, 4)
+ |> dynamic.from
+ |> dynamic.typed_tuple4(
+ dynamic.int,
+ dynamic.string,
+ dynamic.float,
+ dynamic.int,
+ )
+ |> should.equal(Ok(#(1, "", 3.0, 4)))
+
+ #(1, 2, 3, "")
+ |> dynamic.from
+ |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected an int, got a binary"))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected a 4 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int)
+ |> should.equal(Error("Expected a 4 element tuple, got an int"))
+ }
+
+ pub fn tuple5_test() {
+ #(1, 2, 3, 4, 5)
+ |> dynamic.from
+ |> dynamic.tuple5
+ |> should.equal(Ok(#(
+ dynamic.from(1),
+ dynamic.from(2),
+ dynamic.from(3),
+ dynamic.from(4),
+ dynamic.from(5),
+ )))
+
+ #(1, "", 3.0, 4, 5)
+ |> dynamic.from
+ |> dynamic.tuple5
+ |> should.equal(Ok(#(
+ dynamic.from(1),
+ dynamic.from(""),
+ dynamic.from(3.0),
+ dynamic.from(4),
+ dynamic.from(5),
+ )))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.tuple5
+ |> should.equal(Error("Expected a 5 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.tuple5
+ |> should.equal(Error("Expected a 5 element tuple, got an int"))
+ }
+
+ pub fn typed_tuple5_test() {
+ #(1, 2, 3, 4, 5)
+ |> dynamic.from
+ |> dynamic.typed_tuple5(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Ok(#(1, 2, 3, 4, 5)))
+
+ #(1, "", 3.0, 4, 5)
+ |> dynamic.from
+ |> dynamic.typed_tuple5(
+ dynamic.int,
+ dynamic.string,
+ dynamic.float,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Ok(#(1, "", 3.0, 4, 5)))
+
+ #(1, 2, 3, 4, "")
+ |> dynamic.from
+ |> dynamic.typed_tuple5(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error("Expected an int, got a binary"))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.typed_tuple5(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error("Expected a 5 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_tuple5(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error("Expected a 5 element tuple, got an int"))
+ }
+
+ pub fn tuple6_test() {
+ #(1, 2, 3, 4, 5, 6)
+ |> dynamic.from
+ |> dynamic.tuple6
+ |> should.equal(Ok(#(
+ dynamic.from(1),
+ dynamic.from(2),
+ dynamic.from(3),
+ dynamic.from(4),
+ dynamic.from(5),
+ dynamic.from(6),
+ )))
+
+ #(1, "", 3.0, 4, 5, 6)
+ |> dynamic.from
+ |> dynamic.tuple6
+ |> should.equal(Ok(#(
+ dynamic.from(1),
+ dynamic.from(""),
+ dynamic.from(3.0),
+ dynamic.from(4),
+ dynamic.from(5),
+ dynamic.from(6),
+ )))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.tuple6
+ |> should.equal(Error("Expected a 6 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.tuple6
+ |> should.equal(Error("Expected a 6 element tuple, got an int"))
+ }
+
+ pub fn typed_tuple6_test() {
+ #(1, 2, 3, 4, 5, 6)
+ |> dynamic.from
+ |> dynamic.typed_tuple6(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Ok(#(1, 2, 3, 4, 5, 6)))
+
+ #(1, "", 3.0, 4, 5, 6)
+ |> dynamic.from
+ |> dynamic.typed_tuple6(
+ dynamic.int,
+ dynamic.string,
+ dynamic.float,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Ok(#(1, "", 3.0, 4, 5, 6)))
+
+ #(1, 2, 3, 4, 5, "")
+ |> dynamic.from
+ |> dynamic.typed_tuple6(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error("Expected an int, got a binary"))
+
+ #(1, 2)
+ |> dynamic.from
+ |> dynamic.typed_tuple6(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error("Expected a 6 element tuple, got a 2 element tuple"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_tuple6(
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ dynamic.int,
+ )
+ |> should.equal(Error("Expected a 6 element tuple, got an int"))
+ }
+
+ pub fn map_test() {
+ map.new()
+ |> dynamic.from
+ |> dynamic.map
+ |> should.equal(Ok(map.new()))
+
+ 1
+ |> dynamic.from
+ |> dynamic.map
+ |> should.equal(Error("Expected a map, got an int"))
+ }
+
+ pub fn list_test() {
+ []
+ |> dynamic.from
+ |> dynamic.list
+ |> should.equal(Ok([]))
+
+ [1, 2]
+ |> dynamic.from
+ |> dynamic.list
+ |> should.equal(Ok([dynamic.from(1), dynamic.from(2)]))
+
+ [dynamic.from(1), dynamic.from(2.0)]
+ |> dynamic.from
+ |> dynamic.list
+ |> should.equal(Ok([dynamic.from(1), dynamic.from(2.0)]))
+
+ 1
+ |> dynamic.from
+ |> dynamic.list
+ |> should.equal(Error("Expected a list, got an int"))
+ }
+
+ pub fn result_test() {
+ Ok(1)
+ |> dynamic.from
+ |> dynamic.result
+ |> should.equal(Ok(Ok(dynamic.from(1))))
+
+ Error("error")
+ |> dynamic.from
+ |> dynamic.result
+ |> should.equal(Ok(Error(dynamic.from("error"))))
+
+ 1
+ |> dynamic.from
+ |> dynamic.result
+ |> should.equal(Error("Expected a 2 element tuple, got an int"))
+
+ let tag = atom.create_from_string("bad")
+
+ #(tag, "value")
+ |> dynamic.from
+ |> dynamic.result
+ |> should.equal(Error("Expected a tag of \"ok\" or \"error\", got \"bad\""))
+ }
+
+ pub fn typed_result_test() {
+ Ok(1)
+ |> dynamic.from
+ |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
+ |> should.equal(Ok(Ok(1)))
+
+ Error("error")
+ |> dynamic.from
+ |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
+ |> should.equal(Ok(Error("error")))
+
+ Ok("1")
+ |> dynamic.from
+ |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
+ |> should.equal(Error("Expected an int, got a binary"))
+
+ Error(1)
+ |> dynamic.from
+ |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
+ |> should.equal(Error("Expected a bit_string, got an int"))
+
+ 1
+ |> dynamic.from
+ |> dynamic.typed_result(ok: dynamic.int, error: dynamic.string)
+ |> should.equal(Error("Expected a 2 element tuple, got an int"))
+ }
}
diff --git a/test/gleam/float_test.gleam b/test/gleam/float_test.gleam
index 3e0e6f6..79dba56 100644
--- a/test/gleam/float_test.gleam
+++ b/test/gleam/float_test.gleam
@@ -1,274 +1,276 @@
-import gleam/should
-import gleam/float
-import gleam/order
-
-pub fn parse_test() {
- "1.23"
- |> float.parse
- |> should.equal(Ok(1.23))
-
- "5.0"
- |> float.parse
- |> should.equal(Ok(5.0))
-
- "0.123456789"
- |> float.parse
- |> should.equal(Ok(0.123456789))
-
- ""
- |> float.parse
- |> should.equal(Error(Nil))
-
- "what"
- |> float.parse
- |> should.equal(Error(Nil))
-
- "1"
- |> float.parse
- |> should.equal(Error(Nil))
-}
+if erlang {
+ import gleam/should
+ import gleam/float
+ import gleam/order
+
+ pub fn parse_test() {
+ "1.23"
+ |> float.parse
+ |> should.equal(Ok(1.23))
+
+ "5.0"
+ |> float.parse
+ |> should.equal(Ok(5.0))
+
+ "0.123456789"
+ |> float.parse
+ |> should.equal(Ok(0.123456789))
+
+ ""
+ |> float.parse
+ |> should.equal(Error(Nil))
+
+ "what"
+ |> float.parse
+ |> should.equal(Error(Nil))
+
+ "1"
+ |> float.parse
+ |> should.equal(Error(Nil))
+ }
+
+ pub fn to_string_test() {
+ 123.0
+ |> float.to_string
+ |> should.equal("123.0")
+
+ -8.1
+ |> float.to_string
+ |> should.equal("-8.1")
+ }
+
+ pub fn clamp_test() {
+ float.clamp(1.4, min: 1.3, max: 1.5)
+ |> should.equal(1.4)
+
+ float.clamp(1.2, min: 1.3, max: 1.5)
+ |> should.equal(1.3)
+
+ float.clamp(1.6, min: 1.3, max: 1.5)
+ |> should.equal(1.5)
+ }
+
+ pub fn compare_test() {
+ float.compare(0., 0.)
+ |> should.equal(order.Eq)
+
+ float.compare(0.1, 0.1)
+ |> should.equal(order.Eq)
+
+ float.compare(0., 0.1)
+ |> should.equal(order.Lt)
+
+ float.compare(-2., -1.9)
+ |> should.equal(order.Lt)
+
+ float.compare(2., 1.9)
+ |> should.equal(order.Gt)
+
+ float.compare(-1.9, -2.)
+ |> should.equal(order.Gt)
+ }
+
+ pub fn ceiling_test() {
+ 8.1
+ |> float.ceiling
+ |> should.equal(9.0)
+
+ -8.1
+ |> float.ceiling
+ |> should.equal(-8.0)
+
+ -8.0
+ |> float.ceiling
+ |> should.equal(-8.0)
+ }
-pub fn to_string_test() {
- 123.0
- |> float.to_string
- |> should.equal("123.0")
+ pub fn floor_test() {
+ 8.1
+ |> float.floor
+ |> should.equal(8.0)
- -8.1
- |> float.to_string
- |> should.equal("-8.1")
-}
+ -8.1
+ |> float.floor
+ |> should.equal(-9.0)
-pub fn clamp_test() {
- float.clamp(1.4, min: 1.3, max: 1.5)
- |> should.equal(1.4)
+ -8.0
+ |> float.floor
+ |> should.equal(-8.0)
+ }
- float.clamp(1.2, min: 1.3, max: 1.5)
- |> should.equal(1.3)
+ pub fn round_test() {
+ 8.1
+ |> float.round
+ |> should.equal(8)
- float.clamp(1.6, min: 1.3, max: 1.5)
- |> should.equal(1.5)
-}
+ 8.4
+ |> float.round
+ |> should.equal(8)
-pub fn compare_test() {
- float.compare(0., 0.)
- |> should.equal(order.Eq)
+ 8.499
+ |> float.round
+ |> should.equal(8)
- float.compare(0.1, 0.1)
- |> should.equal(order.Eq)
+ 8.5
+ |> float.round
+ |> should.equal(9)
- float.compare(0., 0.1)
- |> should.equal(order.Lt)
+ -8.1
+ |> float.round
+ |> should.equal(-8)
- float.compare(-2., -1.9)
- |> should.equal(order.Lt)
+ -7.5
+ |> float.round
+ |> should.equal(-8)
+ }
- float.compare(2., 1.9)
- |> should.equal(order.Gt)
+ pub fn truncate_test() {
+ 8.1
+ |> float.truncate
+ |> should.equal(8)
- float.compare(-1.9, -2.)
- |> should.equal(order.Gt)
-}
+ 8.4
+ |> float.truncate
+ |> should.equal(8)
-pub fn ceiling_test() {
- 8.1
- |> float.ceiling
- |> should.equal(9.0)
+ 8.499
+ |> float.truncate
+ |> should.equal(8)
- -8.1
- |> float.ceiling
- |> should.equal(-8.0)
+ 8.5
+ |> float.truncate
+ |> should.equal(8)
- -8.0
- |> float.ceiling
- |> should.equal(-8.0)
-}
+ -8.1
+ |> float.truncate
+ |> should.equal(-8)
-pub fn floor_test() {
- 8.1
- |> float.floor
- |> should.equal(8.0)
+ -7.5
+ |> float.truncate
+ |> should.equal(-7)
+ }
- -8.1
- |> float.floor
- |> should.equal(-9.0)
+ pub fn min_test() {
+ float.min(0., 0.)
+ |> should.equal(0.)
- -8.0
- |> float.floor
- |> should.equal(-8.0)
-}
+ float.min(0.3, 1.5)
+ |> should.equal(0.3)
-pub fn round_test() {
- 8.1
- |> float.round
- |> should.equal(8)
+ float.min(1., 0.)
+ |> should.equal(0.)
- 8.4
- |> float.round
- |> should.equal(8)
+ float.min(-1.7, 2.5)
+ |> should.equal(-1.7)
- 8.499
- |> float.round
- |> should.equal(8)
+ float.min(-2.2, -2.2)
+ |> should.equal(-2.2)
- 8.5
- |> float.round
- |> should.equal(9)
+ float.min(-1., -1.)
+ |> should.equal(-1.)
- -8.1
- |> float.round
- |> should.equal(-8)
+ float.min(-1.1, -1.)
+ |> should.equal(-1.1)
+ }
- -7.5
- |> float.round
- |> should.equal(-8)
-}
+ pub fn max_test() {
+ float.max(0., 0.)
+ |> should.equal(0.)
-pub fn truncate_test() {
- 8.1
- |> float.truncate
- |> should.equal(8)
+ float.max(0.3, 1.5)
+ |> should.equal(1.5)
- 8.4
- |> float.truncate
- |> should.equal(8)
+ float.max(1., 0.)
+ |> should.equal(1.)
- 8.499
- |> float.truncate
- |> should.equal(8)
+ float.max(-1.7, 2.5)
+ |> should.equal(2.5)
- 8.5
- |> float.truncate
- |> should.equal(8)
+ float.max(-2.2, -2.2)
+ |> should.equal(-2.2)
- -8.1
- |> float.truncate
- |> should.equal(-8)
+ float.max(-1., -1.)
+ |> should.equal(-1.)
- -7.5
- |> float.truncate
- |> should.equal(-7)
-}
+ float.max(-1.1, -1.)
+ |> should.equal(-1.)
+ }
-pub fn min_test() {
- float.min(0., 0.)
- |> should.equal(0.)
+ pub fn absolute_value_test() {
+ float.absolute_value(-1.0)
+ |> should.equal(1.0)
- float.min(0.3, 1.5)
- |> should.equal(0.3)
+ float.absolute_value(-20.6)
+ |> should.equal(20.6)
- float.min(1., 0.)
- |> should.equal(0.)
+ float.absolute_value(0.0)
+ |> should.equal(0.0)
- float.min(-1.7, 2.5)
- |> should.equal(-1.7)
+ float.absolute_value(1.0)
+ |> should.equal(1.0)
- float.min(-2.2, -2.2)
- |> should.equal(-2.2)
+ float.absolute_value(25.2)
+ |> should.equal(25.2)
+ }
- float.min(-1., -1.)
- |> should.equal(-1.)
+ pub fn power_test() {
+ float.power(2.0, 2.0)
+ |> should.equal(4.0)
- float.min(-1.1, -1.)
- |> should.equal(-1.1)
-}
-
-pub fn max_test() {
- float.max(0., 0.)
- |> should.equal(0.)
+ float.power(-5.0, 3.0)
+ |> should.equal(-125.0)
- float.max(0.3, 1.5)
- |> should.equal(1.5)
+ float.power(10.5, 0.0)
+ |> should.equal(1.0)
- float.max(1., 0.)
- |> should.equal(1.)
+ float.power(16.0, 0.5)
+ |> should.equal(4.0)
- float.max(-1.7, 2.5)
- |> should.equal(2.5)
+ float.power(2.0, -1.0)
+ |> should.equal(0.5)
+ }
- float.max(-2.2, -2.2)
- |> should.equal(-2.2)
+ pub fn square_root_test() {
+ float.square_root(4.0)
+ |> should.equal(Ok(2.0))
- float.max(-1., -1.)
- |> should.equal(-1.)
-
- float.max(-1.1, -1.)
- |> should.equal(-1.)
-}
+ float.square_root(16.0)
+ |> should.equal(Ok(4.0))
-pub fn absolute_value_test() {
- float.absolute_value(-1.0)
- |> should.equal(1.0)
+ float.square_root(0.0)
+ |> should.equal(Ok(0.0))
- float.absolute_value(-20.6)
- |> should.equal(20.6)
+ float.square_root(-4.0)
+ |> should.equal(Error(Nil))
+ }
- float.absolute_value(0.0)
- |> should.equal(0.0)
-
- float.absolute_value(1.0)
- |> should.equal(1.0)
-
- float.absolute_value(25.2)
- |> should.equal(25.2)
-}
+ pub fn negate_test() {
+ float.negate(-1.)
+ |> should.equal(1.)
-pub fn power_test() {
- float.power(2.0, 2.0)
- |> should.equal(4.0)
+ float.negate(2.)
+ |> should.equal(-2.)
- float.power(-5.0, 3.0)
- |> should.equal(-125.0)
+ float.negate(0.)
+ |> should.equal(0.)
+ }
- float.power(10.5, 0.0)
- |> should.equal(1.0)
+ pub fn sum_test() {
+ float.sum([])
+ |> should.equal(0.0)
- float.power(16.0, 0.5)
- |> should.equal(4.0)
-
- float.power(2.0, -1.0)
- |> should.equal(0.5)
-}
-
-pub fn square_root_test() {
- float.square_root(4.0)
- |> should.equal(Ok(2.0))
-
- float.square_root(16.0)
- |> should.equal(Ok(4.0))
-
- float.square_root(0.0)
- |> should.equal(Ok(0.0))
-
- float.square_root(-4.0)
- |> should.equal(Error(Nil))
-}
-
-pub fn negate_test() {
- float.negate(-1.)
- |> should.equal(1.)
-
- float.negate(2.)
- |> should.equal(-2.)
-
- float.negate(0.)
- |> should.equal(0.)
-}
-
-pub fn sum_test() {
- float.sum([])
- |> should.equal(0.0)
-
- float.sum([1.0, 2.2, 3.3])
- |> should.equal(6.5)
-}
+ float.sum([1.0, 2.2, 3.3])
+ |> should.equal(6.5)
+ }
-pub fn product_test() {
- float.product([])
- |> should.equal(0.)
+ pub fn product_test() {
+ float.product([])
+ |> should.equal(0.)
- float.product([4.])
- |> should.equal(4.)
+ float.product([4.])
+ |> should.equal(4.)
- float.product([2.5, 3.2, 4.2])
- |> should.equal(33.6)
+ float.product([2.5, 3.2, 4.2])
+ |> should.equal(33.6)
+ }
}
diff --git a/test/gleam/function_test.gleam b/test/gleam/function_test.gleam
index 721d10d..ec65f63 100644
--- a/test/gleam/function_test.gleam
+++ b/test/gleam/function_test.gleam
@@ -1,126 +1,128 @@
-import gleam/should
-import gleam/dynamic
-import gleam/function
-import gleam/int
-import gleam/list
-import gleam/result
-import gleam/string
-
-pub fn compose_test() {
- let add_two = fn(int: Int) { int + 2 }
- let add_three = fn(int: Int) { int + 3 }
-
- let add_five = function.compose(add_two, add_three)
-
- 1
- |> add_five
- |> should.equal(6)
-
- // Takes a list of ints and returns the head as a string (if there is one, or
- // else "0" if there is not)
- let head_to_string =
- list.head
- |> function.compose(result.unwrap(_, 0))
- |> function.compose(int.to_string)
-
- [1]
- |> head_to_string
- |> should.equal("1")
-
- []
- |> head_to_string
- |> should.equal("0")
-}
+if erlang {
+ import gleam/should
+ import gleam/dynamic
+ import gleam/function
+ import gleam/int
+ import gleam/list
+ import gleam/result
+ import gleam/string
+
+ pub fn compose_test() {
+ let add_two = fn(int: Int) { int + 2 }
+ let add_three = fn(int: Int) { int + 3 }
+
+ let add_five = function.compose(add_two, add_three)
+
+ 1
+ |> add_five
+ |> should.equal(6)
+
+ // Takes a list of ints and returns the head as a string (if there is one, or
+ // else "0" if there is not)
+ let head_to_string =
+ list.head
+ |> function.compose(result.unwrap(_, 0))
+ |> function.compose(int.to_string)
+
+ [1]
+ |> head_to_string
+ |> should.equal("1")
+
+ []
+ |> head_to_string
+ |> should.equal("0")
+ }
-pub fn curry2_test() {
- let fun = fn(a, b) { a + b }
- let curried = function.curry2(fun)
+ pub fn curry2_test() {
+ let fun = fn(a, b) { a + b }
+ let curried = function.curry2(fun)
- curried(1)(2)
- |> should.equal(3)
-}
+ curried(1)(2)
+ |> should.equal(3)
+ }
-pub fn curry3_test() {
- let fun = fn(a, b, c) { a + b + c }
- let curried = function.curry3(fun)
+ pub fn curry3_test() {
+ let fun = fn(a, b, c) { a + b + c }
+ let curried = function.curry3(fun)
- curried(1)(2)(4)
- |> should.equal(7)
-}
-
-pub fn curry4_test() {
- let fun = fn(a, b, c, d) { a + b + c + d }
- let curried = function.curry4(fun)
+ curried(1)(2)(4)
+ |> should.equal(7)
+ }
- curried(1)(2)(4)(8)
- |> should.equal(15)
-}
+ pub fn curry4_test() {
+ let fun = fn(a, b, c, d) { a + b + c + d }
+ let curried = function.curry4(fun)
-pub fn curry5_test() {
- let fun = fn(a, b, c, d, e) { a + b + c + d + e }
- let curried = function.curry5(fun)
+ curried(1)(2)(4)(8)
+ |> should.equal(15)
+ }
- curried(1)(2)(4)(8)(16)
- |> should.equal(31)
-}
+ pub fn curry5_test() {
+ let fun = fn(a, b, c, d, e) { a + b + c + d + e }
+ let curried = function.curry5(fun)
-pub fn curry6_test() {
- let fun = fn(a, b, c, d, e, f) { a + b + c + d + e + f }
- let curried = function.curry6(fun)
+ curried(1)(2)(4)(8)(16)
+ |> should.equal(31)
+ }
- curried(1)(2)(4)(8)(16)(32)
- |> should.equal(63)
-}
+ pub fn curry6_test() {
+ let fun = fn(a, b, c, d, e, f) { a + b + c + d + e + f }
+ let curried = function.curry6(fun)
-pub fn flip_test() {
- let fun = fn(s: String, i: Int) {
- s
- |> string.append("String: '", _)
- |> string.append("', Int: '")
- |> string.append(int.to_string(i))
- |> string.append("'")
+ curried(1)(2)(4)(8)(16)(32)
+ |> should.equal(63)
}
- let flipped_fun = function.flip(fun)
+ pub fn flip_test() {
+ let fun = fn(s: String, i: Int) {
+ s
+ |> string.append("String: '", _)
+ |> string.append("', Int: '")
+ |> string.append(int.to_string(i))
+ |> string.append("'")
+ }
- fun("Bob", 1)
- |> should.equal("String: 'Bob', Int: '1'")
+ let flipped_fun = function.flip(fun)
- flipped_fun(2, "Alice")
- |> should.equal("String: 'Alice', Int: '2'")
-}
+ fun("Bob", 1)
+ |> should.equal("String: 'Bob', Int: '1'")
-pub fn identity_test() {
- 1
- |> function.identity
- |> should.equal(1)
+ flipped_fun(2, "Alice")
+ |> should.equal("String: 'Alice', Int: '2'")
+ }
- ""
- |> function.identity
- |> should.equal("")
+ pub fn identity_test() {
+ 1
+ |> function.identity
+ |> should.equal(1)
- []
- |> function.identity
- |> should.equal([])
+ ""
+ |> function.identity
+ |> should.equal("")
- #(1, 2.0)
- |> function.identity
- |> should.equal(#(1, 2.0))
-}
+ []
+ |> function.identity
+ |> should.equal([])
+
+ #(1, 2.0)
+ |> function.identity
+ |> should.equal(#(1, 2.0))
+ }
-external fn throw(a) -> Nil =
- "erlang" "throw"
+ external fn throw(a) -> Nil =
+ "erlang" "throw"
-external fn raise_error(a) -> Nil =
- "erlang" "error"
+ external fn raise_error(a) -> Nil =
+ "erlang" "error"
-pub fn rescue_test() {
- function.rescue(fn() { 1 })
- |> should.equal(Ok(1))
+ pub fn rescue_test() {
+ function.rescue(fn() { 1 })
+ |> should.equal(Ok(1))
- function.rescue(fn() { throw(1) })
- |> should.equal(Error(function.Thrown(dynamic.from(1))))
+ function.rescue(fn() { throw(1) })
+ |> should.equal(Error(function.Thrown(dynamic.from(1))))
- function.rescue(fn() { raise_error("") })
- |> should.equal(Error(function.Errored(dynamic.from(""))))
+ function.rescue(fn() { raise_error("") })
+ |> should.equal(Error(function.Errored(dynamic.from(""))))
+ }
}
diff --git a/test/gleam/int_test.gleam b/test/gleam/int_test.gleam
index bec9624..31d06de 100644
--- a/test/gleam/int_test.gleam
+++ b/test/gleam/int_test.gleam
@@ -1,228 +1,230 @@
-import gleam/should
-import gleam/int
-import gleam/order
-
-pub fn absolute_value_test() {
- 123
- |> int.absolute_value
- |> should.equal(123)
-
- -123
- |> int.absolute_value
- |> should.equal(123)
-}
+if erlang {
+ import gleam/should
+ import gleam/int
+ import gleam/order
+
+ pub fn absolute_value_test() {
+ 123
+ |> int.absolute_value
+ |> should.equal(123)
-pub fn clamp_test() {
- int.clamp(40, min: 30, max: 50)
- |> should.equal(40)
+ -123
+ |> int.absolute_value
+ |> should.equal(123)
+ }
- int.clamp(20, min: 30, max: 50)
- |> should.equal(30)
+ pub fn clamp_test() {
+ int.clamp(40, min: 30, max: 50)
+ |> should.equal(40)
- int.clamp(60, min: 30, max: 50)
- |> should.equal(50)
+ int.clamp(20, min: 30, max: 50)
+ |> should.equal(30)
- // If the bounds are reversed we return the min
- int.clamp(100, min: 50, max: 30)
- |> should.equal(50)
-}
+ int.clamp(60, min: 30, max: 50)
+ |> should.equal(50)
-pub fn to_string_test() {
- 123
- |> int.to_string
- |> should.equal("123")
+ // If the bounds are reversed we return the min
+ int.clamp(100, min: 50, max: 30)
+ |> should.equal(50)
+ }
- -123
- |> int.to_string
- |> should.equal("-123")
+ pub fn to_string_test() {
+ 123
+ |> int.to_string
+ |> should.equal("123")
- 123
- |> int.to_string
- |> should.equal("123")
-}
+ -123
+ |> int.to_string
+ |> should.equal("-123")
-pub fn parse_test() {
- "123"
- |> int.parse
- |> should.equal(Ok(123))
+ 123
+ |> int.to_string
+ |> should.equal("123")
+ }
- "-123"
- |> int.parse
- |> should.equal(Ok(-123))
+ pub fn parse_test() {
+ "123"
+ |> int.parse
+ |> should.equal(Ok(123))
- "0123"
- |> int.parse
- |> should.equal(Ok(123))
+ "-123"
+ |> int.parse
+ |> should.equal(Ok(-123))
- ""
- |> int.parse
- |> should.equal(Error(Nil))
+ "0123"
+ |> int.parse
+ |> should.equal(Ok(123))
- "what"
- |> int.parse
- |> should.equal(Error(Nil))
+ ""
+ |> int.parse
+ |> should.equal(Error(Nil))
- "1.23"
- |> int.parse
- |> should.equal(Error(Nil))
-}
+ "what"
+ |> int.parse
+ |> should.equal(Error(Nil))
-pub fn to_base_string_test() {
- 100
- |> int.to_base_string(16)
- |> should.equal("64")
+ "1.23"
+ |> int.parse
+ |> should.equal(Error(Nil))
+ }
- -100
- |> int.to_base_string(16)
- |> should.equal("-64")
-}
+ pub fn to_base_string_test() {
+ 100
+ |> int.to_base_string(16)
+ |> should.equal("64")
-pub fn to_float_test() {
- int.to_float(1)
- |> should.equal(1.)
+ -100
+ |> int.to_base_string(16)
+ |> should.equal("-64")
+ }
- int.to_float(5)
- |> should.equal(5.)
+ pub fn to_float_test() {
+ int.to_float(1)
+ |> should.equal(1.)
- int.to_float(0)
- |> should.equal(0.)
+ int.to_float(5)
+ |> should.equal(5.)
- int.to_float(-5)
- |> should.equal(-5.)
-}
+ int.to_float(0)
+ |> should.equal(0.)
-pub fn compare_test() {
- int.compare(0, 0)
- |> should.equal(order.Eq)
+ int.to_float(-5)
+ |> should.equal(-5.)
+ }
- int.compare(1, 1)
- |> should.equal(order.Eq)
+ pub fn compare_test() {
+ int.compare(0, 0)
+ |> should.equal(order.Eq)
- int.compare(0, 1)
- |> should.equal(order.Lt)
+ int.compare(1, 1)
+ |> should.equal(order.Eq)
- int.compare(-2, -1)
- |> should.equal(order.Lt)
+ int.compare(0, 1)
+ |> should.equal(order.Lt)
- int.compare(2, 1)
- |> should.equal(order.Gt)
+ int.compare(-2, -1)
+ |> should.equal(order.Lt)
- int.compare(-1, -2)
- |> should.equal(order.Gt)
-}
+ int.compare(2, 1)
+ |> should.equal(order.Gt)
-pub fn min_test() {
- int.min(0, 0)
- |> should.equal(0)
+ int.compare(-1, -2)
+ |> should.equal(order.Gt)
+ }
- int.min(0, 1)
- |> should.equal(0)
+ pub fn min_test() {
+ int.min(0, 0)
+ |> should.equal(0)
- int.min(1, 0)
- |> should.equal(0)
+ int.min(0, 1)
+ |> should.equal(0)
- int.min(-1, 2)
- |> should.equal(-1)
+ int.min(1, 0)
+ |> should.equal(0)
- int.min(2, -2)
- |> should.equal(-2)
+ int.min(-1, 2)
+ |> should.equal(-1)
- int.min(-1, -1)
- |> should.equal(-1)
-}
+ int.min(2, -2)
+ |> should.equal(-2)
-pub fn max_test() {
- int.max(0, 0)
- |> should.equal(0)
+ int.min(-1, -1)
+ |> should.equal(-1)
+ }
- int.max(0, 1)
- |> should.equal(1)
+ pub fn max_test() {
+ int.max(0, 0)
+ |> should.equal(0)
- int.max(1, 0)
- |> should.equal(1)
+ int.max(0, 1)
+ |> should.equal(1)
- int.max(-1, 2)
- |> should.equal(2)
+ int.max(1, 0)
+ |> should.equal(1)
- int.max(2, -2)
- |> should.equal(2)
+ int.max(-1, 2)
+ |> should.equal(2)
- int.max(-1, -1)
- |> should.equal(-1)
-}
+ int.max(2, -2)
+ |> should.equal(2)
-pub fn is_even_test() {
- int.is_even(0)
- |> should.be_true
+ int.max(-1, -1)
+ |> should.equal(-1)
+ }
- int.is_even(2)
- |> should.be_true
+ pub fn is_even_test() {
+ int.is_even(0)
+ |> should.be_true
- int.is_even(-2)
- |> should.be_true
+ int.is_even(2)
+ |> should.be_true
- int.is_even(10006)
- |> should.be_true
+ int.is_even(-2)
+ |> should.be_true
- int.is_even(1)
- |> should.be_false
+ int.is_even(10006)
+ |> should.be_true
- int.is_even(-3)
- |> should.be_false
+ int.is_even(1)
+ |> should.be_false
- int.is_even(10005)
- |> should.be_false
-}
+ int.is_even(-3)
+ |> should.be_false
-pub fn is_odd_test() {
- int.is_odd(0)
- |> should.be_false
+ int.is_even(10005)
+ |> should.be_false
+ }
- int.is_odd(2)
- |> should.be_false
+ pub fn is_odd_test() {
+ int.is_odd(0)
+ |> should.be_false
- int.is_odd(-2)
- |> should.be_false
+ int.is_odd(2)
+ |> should.be_false
- int.is_odd(10006)
- |> should.be_false
+ int.is_odd(-2)
+ |> should.be_false
- int.is_odd(1)
- |> should.be_true
+ int.is_odd(10006)
+ |> should.be_false
- int.is_odd(-3)
- |> should.be_true
+ int.is_odd(1)
+ |> should.be_true
- int.is_odd(10005)
- |> should.be_true
-}
+ int.is_odd(-3)
+ |> should.be_true
-pub fn negate_test() {
- int.negate(-1)
- |> should.equal(1)
+ int.is_odd(10005)
+ |> should.be_true
+ }
- int.negate(2)
- |> should.equal(-2)
+ pub fn negate_test() {
+ int.negate(-1)
+ |> should.equal(1)
- int.negate(0)
- |> should.equal(0)
-}
+ int.negate(2)
+ |> should.equal(-2)
-pub fn sum_test() {
- int.sum([])
- |> should.equal(0)
+ int.negate(0)
+ |> should.equal(0)
+ }
- int.sum([1, 2, 3])
- |> should.equal(6)
-}
+ pub fn sum_test() {
+ int.sum([])
+ |> should.equal(0)
+
+ int.sum([1, 2, 3])
+ |> should.equal(6)
+ }
-pub fn product_test() {
- int.product([])
- |> should.equal(0)
+ pub fn product_test() {
+ int.product([])
+ |> should.equal(0)
- int.product([4])
- |> should.equal(4)
+ int.product([4])
+ |> should.equal(4)
- int.product([1, 2, 3])
- |> should.equal(6)
+ int.product([1, 2, 3])
+ |> should.equal(6)
+ }
}
diff --git a/test/gleam/iterator_test.gleam b/test/gleam/iterator_test.gleam
index 0fb7143..0c0176f 100644
--- a/test/gleam/iterator_test.gleam
+++ b/test/gleam/iterator_test.gleam
@@ -1,421 +1,423 @@
-import gleam/should
-import gleam/iterator.{Done, Next}
-import gleam/list
-import gleam/map
-
-// a |> from_list |> to_list == a
-pub fn to_from_list_test() {
- let test = fn(subject) {
- subject
- |> iterator.from_list
- |> iterator.to_list
- |> should.equal(subject)
+if erlang {
+ import gleam/should
+ import gleam/iterator.{Done, Next}
+ import gleam/list
+ import gleam/map
+
+ // a |> from_list |> to_list == a
+ pub fn to_from_list_test() {
+ let test = fn(subject) {
+ subject
+ |> iterator.from_list
+ |> iterator.to_list
+ |> should.equal(subject)
+ }
+
+ test([])
+ test([1])
+ test([1, 2])
+ test([1, 2, 4, 8])
}
- test([])
- test([1])
- test([1, 2])
- test([1, 2, 4, 8])
-}
+ pub fn step_test() {
+ let test = fn(subject) {
+ let step =
+ subject
+ |> iterator.from_list
+ |> iterator.step
+
+ case subject {
+ [] ->
+ step
+ |> should.equal(Done)
+
+ [h, ..t] ->
+ step
+ |> should.equal(Next(h, iterator.from_list(t)))
+ }
+ }
-pub fn step_test() {
- let test = fn(subject) {
- let step =
+ test([])
+ test([1])
+ test([1, 2])
+ test([1, 2, 3])
+ }
+
+ // a |> from_list |> take(n) == a |> list.take(_, n)
+ pub fn take_test() {
+ let test = fn(n, subject) {
subject
|> iterator.from_list
- |> iterator.step
+ |> iterator.take(n)
+ |> iterator.to_list
+ |> should.equal(list.take(subject, n))
+ }
- case subject {
- [] ->
- step
- |> should.equal(Done)
+ test(0, [])
+ test(1, [])
+ test(-1, [])
+ test(0, [0])
+ test(1, [0])
+ test(-1, [0])
+ test(0, [0, 1, 2, 3, 4])
+ test(1, [0, 1, 2, 3, 4])
+ test(2, [0, 1, 2, 3, 4])
+ test(22, [0, 1, 2, 3, 4])
+ }
- [h, ..t] ->
- step
- |> should.equal(Next(h, iterator.from_list(t)))
+ // a |> from_list |> fold(a, f) == a |> list.fold(_, a, f)
+ pub fn fold_test() {
+ let test = fn(subject, acc, f) {
+ subject
+ |> iterator.from_list
+ |> iterator.fold(acc, f)
+ |> should.equal(list.fold(subject, acc, f))
}
- }
- test([])
- test([1])
- test([1, 2])
- test([1, 2, 3])
-}
+ let f = fn(e, acc) { [e, ..acc] }
+ test([], [], f)
+ test([1], [], f)
+ test([1, 2, 3], [], f)
+ test([1, 2, 3, 4, 5, 6, 7, 8], [], f)
+ }
-// a |> from_list |> take(n) == a |> list.take(_, n)
-pub fn take_test() {
- let test = fn(n, subject) {
- subject
- |> iterator.from_list
- |> iterator.take(n)
- |> iterator.to_list
- |> should.equal(list.take(subject, n))
- }
-
- test(0, [])
- test(1, [])
- test(-1, [])
- test(0, [0])
- test(1, [0])
- test(-1, [0])
- test(0, [0, 1, 2, 3, 4])
- test(1, [0, 1, 2, 3, 4])
- test(2, [0, 1, 2, 3, 4])
- test(22, [0, 1, 2, 3, 4])
-}
+ // a |> from_list |> map(f) |> to_list == a |> list.map(_, f)
+ pub fn map_test() {
+ let test = fn(subject, f) {
+ subject
+ |> iterator.from_list
+ |> iterator.map(f)
+ |> iterator.to_list
+ |> should.equal(list.map(subject, f))
+ }
-// a |> from_list |> fold(a, f) == a |> list.fold(_, a, f)
-pub fn fold_test() {
- let test = fn(subject, acc, f) {
- subject
- |> iterator.from_list
- |> iterator.fold(acc, f)
- |> should.equal(list.fold(subject, acc, f))
+ let f = fn(e) { e * 2 }
+ test([], f)
+ test([1], f)
+ test([1, 2, 3], f)
+ test([1, 2, 3, 4, 5, 6, 7, 8], f)
}
- let f = fn(e, acc) { [e, ..acc] }
- test([], [], f)
- test([1], [], f)
- test([1, 2, 3], [], f)
- test([1, 2, 3, 4, 5, 6, 7, 8], [], f)
-}
+ // a |> from_list |> flat_map(f) |> to_list ==
+ // a |> list.map(f) |> list.map(to_list) |> list.flatten
+ pub fn flat_map_test() {
+ let test = fn(subject, f) {
+ subject
+ |> iterator.from_list
+ |> iterator.flat_map(f)
+ |> iterator.to_list
+ |> should.equal(
+ subject
+ |> list.map(f)
+ |> list.map(iterator.to_list)
+ |> list.flatten,
+ )
+ }
-// a |> from_list |> map(f) |> to_list == a |> list.map(_, f)
-pub fn map_test() {
- let test = fn(subject, f) {
- subject
- |> iterator.from_list
- |> iterator.map(f)
- |> iterator.to_list
- |> should.equal(list.map(subject, f))
+ let f = fn(i) { iterator.range(i, i + 2) }
+
+ test([], f)
+ test([1], f)
+ test([1, 2], f)
}
- let f = fn(e) { e * 2 }
- test([], f)
- test([1], f)
- test([1, 2, 3], f)
- test([1, 2, 3, 4, 5, 6, 7, 8], f)
-}
+ // a |> from_list |> append(from_list(b)) |> to_list == list.flatten([a, b])
+ pub fn append_test() {
+ let test = fn(left, right) {
+ left
+ |> iterator.from_list
+ |> iterator.append(iterator.from_list(right))
+ |> iterator.to_list
+ |> should.equal(list.flatten([left, right]))
+ }
-// a |> from_list |> flat_map(f) |> to_list ==
-// a |> list.map(f) |> list.map(to_list) |> list.flatten
-pub fn flat_map_test() {
- let test = fn(subject, f) {
- subject
- |> iterator.from_list
- |> iterator.flat_map(f)
- |> iterator.to_list
- |> should.equal(
- subject
- |> list.map(f)
- |> list.map(iterator.to_list)
- |> list.flatten,
- )
+ test([], [])
+ test([1], [2])
+ test([1, 2], [3, 4])
}
- let f = fn(i) { iterator.range(i, i + 2) }
-
- test([], f)
- test([1], f)
- test([1, 2], f)
-}
+ // a |> list.map(from_list) |> flatten |> to_list == list.flatten(a)
+ pub fn flatten_test() {
+ let test = fn(lists) {
+ lists
+ |> list.map(iterator.from_list)
+ |> iterator.from_list
+ |> iterator.flatten
+ |> iterator.to_list
+ |> should.equal(list.flatten(lists))
+ }
-// a |> from_list |> append(from_list(b)) |> to_list == list.flatten([a, b])
-pub fn append_test() {
- let test = fn(left, right) {
- left
- |> iterator.from_list
- |> iterator.append(iterator.from_list(right))
- |> iterator.to_list
- |> should.equal(list.flatten([left, right]))
+ test([[], []])
+ test([[1], [2]])
+ test([[1, 2], [3, 4]])
}
- test([], [])
- test([1], [2])
- test([1, 2], [3, 4])
-}
+ // a |> from_list |> filter(f) |> to_list == a |> list.filter(_, f)
+ pub fn filter_test() {
+ let test = fn(subject, f) {
+ subject
+ |> iterator.from_list
+ |> iterator.filter(f)
+ |> iterator.to_list
+ |> should.equal(list.filter(subject, f))
+ }
-// a |> list.map(from_list) |> flatten |> to_list == list.flatten(a)
-pub fn flatten_test() {
- let test = fn(lists) {
- lists
- |> list.map(iterator.from_list)
- |> iterator.from_list
- |> iterator.flatten
- |> iterator.to_list
- |> should.equal(list.flatten(lists))
+ let even = fn(x) { x % 2 == 0 }
+ test([], even)
+ test([1], even)
+ test([1, 2], even)
+ test([1, 2, 3], even)
+ test([1, 2, 3, 4], even)
+ test([1, 2, 3, 4, 5], even)
+ test([1, 2, 3, 4, 5, 6], even)
}
- test([[], []])
- test([[1], [2]])
- test([[1, 2], [3, 4]])
-}
+ pub fn repeat_test() {
+ 1
+ |> iterator.repeat
+ |> iterator.take(5)
+ |> iterator.to_list
+ |> should.equal([1, 1, 1, 1, 1])
+ }
-// a |> from_list |> filter(f) |> to_list == a |> list.filter(_, f)
-pub fn filter_test() {
- let test = fn(subject, f) {
- subject
+ pub fn cycle_test() {
+ [1, 2, 3]
|> iterator.from_list
- |> iterator.filter(f)
+ |> iterator.cycle
+ |> iterator.take(9)
|> iterator.to_list
- |> should.equal(list.filter(subject, f))
+ |> should.equal([1, 2, 3, 1, 2, 3, 1, 2, 3])
}
- let even = fn(x) { x % 2 == 0 }
- test([], even)
- test([1], even)
- test([1, 2], even)
- test([1, 2, 3], even)
- test([1, 2, 3, 4], even)
- test([1, 2, 3, 4, 5], even)
- test([1, 2, 3, 4, 5, 6], even)
-}
+ pub fn unfold_test() {
+ iterator.unfold(2, fn(acc) { iterator.Next(acc, acc * 2) })
+ |> iterator.take(5)
+ |> iterator.to_list
+ |> should.equal([2, 4, 8, 16, 32])
-pub fn repeat_test() {
- 1
- |> iterator.repeat
- |> iterator.take(5)
- |> iterator.to_list
- |> should.equal([1, 1, 1, 1, 1])
-}
+ iterator.unfold(2, fn(_) { iterator.Done })
+ |> iterator.take(5)
+ |> iterator.to_list
+ |> should.equal([])
-pub fn cycle_test() {
- [1, 2, 3]
- |> iterator.from_list
- |> iterator.cycle
- |> iterator.take(9)
- |> iterator.to_list
- |> should.equal([1, 2, 3, 1, 2, 3, 1, 2, 3])
-}
+ fn(n) {
+ case n {
+ 0 -> iterator.Done
+ n -> iterator.Next(element: n, accumulator: n - 1)
+ }
+ }
+ |> iterator.unfold(from: 5)
+ |> iterator.to_list
+ |> should.equal([5, 4, 3, 2, 1])
+ }
-pub fn unfold_test() {
- iterator.unfold(2, fn(acc) { iterator.Next(acc, acc * 2) })
- |> iterator.take(5)
- |> iterator.to_list
- |> should.equal([2, 4, 8, 16, 32])
-
- iterator.unfold(2, fn(_) { iterator.Done })
- |> iterator.take(5)
- |> iterator.to_list
- |> should.equal([])
-
- fn(n) {
- case n {
- 0 -> iterator.Done
- n -> iterator.Next(element: n, accumulator: n - 1)
+ pub fn range_test() {
+ let test = fn(a, b, expected) {
+ iterator.range(a, b)
+ |> iterator.to_list
+ |> should.equal(expected)
}
+
+ test(0, 0, [])
+ test(1, 1, [])
+ test(-1, -1, [])
+ test(0, 1, [0])
+ test(0, 5, [0, 1, 2, 3, 4])
+ test(1, -5, [1, 0, -1, -2, -3, -4])
}
- |> iterator.unfold(from: 5)
- |> iterator.to_list
- |> should.equal([5, 4, 3, 2, 1])
-}
-pub fn range_test() {
- let test = fn(a, b, expected) {
- iterator.range(a, b)
+ pub fn drop_test() {
+ iterator.range(0, 10)
+ |> iterator.drop(5)
|> iterator.to_list
- |> should.equal(expected)
+ |> should.equal([5, 6, 7, 8, 9])
}
- test(0, 0, [])
- test(1, 1, [])
- test(-1, -1, [])
- test(0, 1, [0])
- test(0, 5, [0, 1, 2, 3, 4])
- test(1, -5, [1, 0, -1, -2, -3, -4])
-}
+ type Cat {
+ Cat(id: Int)
+ }
-pub fn drop_test() {
- iterator.range(0, 10)
- |> iterator.drop(5)
- |> iterator.to_list
- |> should.equal([5, 6, 7, 8, 9])
-}
+ pub fn find_test() {
+ iterator.range(0, 10)
+ |> iterator.find(fn(e) { e == 5 })
+ |> should.equal(Ok(5))
-type Cat {
- Cat(id: Int)
-}
+ iterator.range(0, 10)
+ |> iterator.find(fn(e) { e > 10 })
+ |> should.equal(Error(Nil))
-pub fn find_test() {
- iterator.range(0, 10)
- |> iterator.find(fn(e) { e == 5 })
- |> should.equal(Ok(5))
-
- iterator.range(0, 10)
- |> iterator.find(fn(e) { e > 10 })
- |> should.equal(Error(Nil))
-
- iterator.empty()
- |> iterator.find(fn(_x) { True })
- |> should.equal(Error(Nil))
-
- iterator.unfold(
- Cat(id: 1),
- fn(cat: Cat) { iterator.Next(cat, Cat(id: cat.id + 1)) },
- )
- |> iterator.find(fn(cat: Cat) { cat.id == 10 })
- |> should.equal(Ok(Cat(id: 10)))
-}
+ iterator.empty()
+ |> iterator.find(fn(_x) { True })
+ |> should.equal(Error(Nil))
-pub fn index_test() {
- iterator.from_list(["a", "b", "c"])
- |> iterator.index
- |> iterator.to_list
- |> should.equal([#(0, "a"), #(1, "b"), #(2, "c")])
-}
+ iterator.unfold(
+ Cat(id: 1),
+ fn(cat: Cat) { iterator.Next(cat, Cat(id: cat.id + 1)) },
+ )
+ |> iterator.find(fn(cat: Cat) { cat.id == 10 })
+ |> should.equal(Ok(Cat(id: 10)))
+ }
-pub fn iterate_test() {
- fn(x) { x * 3 }
- |> iterator.iterate(from: 1)
- |> iterator.take(5)
- |> iterator.to_list
- |> should.equal([1, 3, 9, 27, 81])
-}
+ pub fn index_test() {
+ iterator.from_list(["a", "b", "c"])
+ |> iterator.index
+ |> iterator.to_list
+ |> should.equal([#(0, "a"), #(1, "b"), #(2, "c")])
+ }
-pub fn take_while_test() {
- iterator.from_list([1, 2, 3, 2, 4])
- |> iterator.take_while(satisfying: fn(x) { x < 3 })
- |> iterator.to_list
- |> should.equal([1, 2])
-}
+ pub fn iterate_test() {
+ fn(x) { x * 3 }
+ |> iterator.iterate(from: 1)
+ |> iterator.take(5)
+ |> iterator.to_list
+ |> should.equal([1, 3, 9, 27, 81])
+ }
-pub fn drop_while_test() {
- iterator.from_list([1, 2, 3, 4, 2, 5])
- |> iterator.drop_while(satisfying: fn(x) { x < 4 })
- |> iterator.to_list
- |> should.equal([4, 2, 5])
-}
+ pub fn take_while_test() {
+ iterator.from_list([1, 2, 3, 2, 4])
+ |> iterator.take_while(satisfying: fn(x) { x < 3 })
+ |> iterator.to_list
+ |> should.equal([1, 2])
+ }
-pub fn scan_test() {
- iterator.from_list([1, 2, 3, 4, 5])
- |> iterator.scan(from: 0, with: fn(el, acc) { acc + el })
- |> iterator.to_list
- |> should.equal([1, 3, 6, 10, 15])
-}
+ pub fn drop_while_test() {
+ iterator.from_list([1, 2, 3, 4, 2, 5])
+ |> iterator.drop_while(satisfying: fn(x) { x < 4 })
+ |> iterator.to_list
+ |> should.equal([4, 2, 5])
+ }
-pub fn zip_test() {
- iterator.from_list(["a", "b", "c"])
- |> iterator.zip(iterator.range(20, 30))
- |> iterator.to_list
- |> should.equal([#("a", 20), #("b", 21), #("c", 22)])
-}
+ pub fn scan_test() {
+ iterator.from_list([1, 2, 3, 4, 5])
+ |> iterator.scan(from: 0, with: fn(el, acc) { acc + el })
+ |> iterator.to_list
+ |> should.equal([1, 3, 6, 10, 15])
+ }
-pub fn chunk_test() {
- iterator.from_list([1, 2, 2, 3, 4, 4, 6, 7, 7])
- |> iterator.chunk(by: fn(n) { n % 2 })
- |> iterator.to_list
- |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]])
-}
+ pub fn zip_test() {
+ iterator.from_list(["a", "b", "c"])
+ |> iterator.zip(iterator.range(20, 30))
+ |> iterator.to_list
+ |> should.equal([#("a", 20), #("b", 21), #("c", 22)])
+ }
-pub fn sized_chunk_test() {
- iterator.from_list([1, 2, 3, 4, 5, 6])
- |> iterator.sized_chunk(into: 2)
- |> iterator.to_list
- |> should.equal([[1, 2], [3, 4], [5, 6]])
+ pub fn chunk_test() {
+ iterator.from_list([1, 2, 2, 3, 4, 4, 6, 7, 7])
+ |> iterator.chunk(by: fn(n) { n % 2 })
+ |> iterator.to_list
+ |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]])
+ }
- iterator.from_list([1, 2, 3, 4, 5, 6, 7, 8])
- |> iterator.sized_chunk(into: 3)
- |> iterator.to_list
- |> should.equal([[1, 2, 3], [4, 5, 6], [7, 8]])
-}
+ pub fn sized_chunk_test() {
+ iterator.from_list([1, 2, 3, 4, 5, 6])
+ |> iterator.sized_chunk(into: 2)
+ |> iterator.to_list
+ |> should.equal([[1, 2], [3, 4], [5, 6]])
-pub fn intersperse_test() {
- iterator.empty()
- |> iterator.intersperse(with: 0)
- |> iterator.to_list
- |> should.equal([])
-
- iterator.from_list([1])
- |> iterator.intersperse(with: 0)
- |> iterator.to_list
- |> should.equal([1])
-
- iterator.from_list([1, 2, 3, 4, 5])
- |> iterator.intersperse(with: 0)
- |> iterator.to_list
- |> should.equal([1, 0, 2, 0, 3, 0, 4, 0, 5])
-}
+ iterator.from_list([1, 2, 3, 4, 5, 6, 7, 8])
+ |> iterator.sized_chunk(into: 3)
+ |> iterator.to_list
+ |> should.equal([[1, 2, 3], [4, 5, 6], [7, 8]])
+ }
-pub fn any_test() {
- iterator.empty()
- |> iterator.any(satisfying: fn(n) { n % 2 == 0 })
- |> should.be_false
+ pub fn intersperse_test() {
+ iterator.empty()
+ |> iterator.intersperse(with: 0)
+ |> iterator.to_list
+ |> should.equal([])
- iterator.from_list([1, 2, 5, 7, 9])
- |> iterator.any(satisfying: fn(n) { n % 2 == 0 })
- |> should.be_true
+ iterator.from_list([1])
+ |> iterator.intersperse(with: 0)
+ |> iterator.to_list
+ |> should.equal([1])
- iterator.from_list([1, 3, 5, 7, 9])
- |> iterator.any(satisfying: fn(n) { n % 2 == 0 })
- |> should.be_false
-}
+ iterator.from_list([1, 2, 3, 4, 5])
+ |> iterator.intersperse(with: 0)
+ |> iterator.to_list
+ |> should.equal([1, 0, 2, 0, 3, 0, 4, 0, 5])
+ }
-pub fn all_test() {
- iterator.empty()
- |> iterator.all(satisfying: fn(n) { n % 2 == 0 })
- |> should.be_true
+ pub fn any_test() {
+ iterator.empty()
+ |> iterator.any(satisfying: fn(n) { n % 2 == 0 })
+ |> should.be_false
- iterator.from_list([2, 4, 6, 8])
- |> iterator.all(satisfying: fn(n) { n % 2 == 0 })
- |> should.be_true
+ iterator.from_list([1, 2, 5, 7, 9])
+ |> iterator.any(satisfying: fn(n) { n % 2 == 0 })
+ |> should.be_true
- iterator.from_list([2, 4, 5, 8])
- |> iterator.all(satisfying: fn(n) { n % 2 == 0 })
- |> should.be_false
-}
+ iterator.from_list([1, 3, 5, 7, 9])
+ |> iterator.any(satisfying: fn(n) { n % 2 == 0 })
+ |> should.be_false
+ }
-pub fn group_test() {
- iterator.from_list([1, 2, 3, 4, 5, 6])
- |> iterator.group(by: fn(n) { n % 3 })
- |> should.equal(map.from_list([#(0, [3, 6]), #(1, [1, 4]), #(2, [2, 5])]))
-}
+ pub fn all_test() {
+ iterator.empty()
+ |> iterator.all(satisfying: fn(n) { n % 2 == 0 })
+ |> should.be_true
-pub fn reduce_test() {
- iterator.empty()
- |> iterator.reduce(with: fn(x, y) { x + y })
- |> should.equal(Error(Nil))
+ iterator.from_list([2, 4, 6, 8])
+ |> iterator.all(satisfying: fn(n) { n % 2 == 0 })
+ |> should.be_true
- iterator.from_list([1, 2, 3, 4, 5])
- |> iterator.reduce(with: fn(x, y) { x + y })
- |> should.equal(Ok(15))
-}
+ iterator.from_list([2, 4, 5, 8])
+ |> iterator.all(satisfying: fn(n) { n % 2 == 0 })
+ |> should.be_false
+ }
-pub fn last_test() {
- iterator.empty()
- |> iterator.last
- |> should.equal(Error(Nil))
+ pub fn group_test() {
+ iterator.from_list([1, 2, 3, 4, 5, 6])
+ |> iterator.group(by: fn(n) { n % 3 })
+ |> should.equal(map.from_list([#(0, [3, 6]), #(1, [1, 4]), #(2, [2, 5])]))
+ }
- iterator.range(1, 10)
- |> iterator.last
- |> should.equal(Ok(9))
-}
+ pub fn reduce_test() {
+ iterator.empty()
+ |> iterator.reduce(with: fn(x, y) { x + y })
+ |> should.equal(Error(Nil))
-pub fn empty_test() {
- iterator.empty()
- |> iterator.to_list
- |> should.equal([])
-}
+ iterator.from_list([1, 2, 3, 4, 5])
+ |> iterator.reduce(with: fn(x, y) { x + y })
+ |> should.equal(Ok(15))
+ }
-pub fn once_test() {
- iterator.once(fn() { 1 })
- |> iterator.to_list
- |> should.equal([1])
-}
+ pub fn last_test() {
+ iterator.empty()
+ |> iterator.last
+ |> should.equal(Error(Nil))
-pub fn single_test() {
- iterator.single(1)
- |> iterator.to_list
- |> should.equal([1])
-}
+ iterator.range(1, 10)
+ |> iterator.last
+ |> should.equal(Ok(9))
+ }
+
+ pub fn empty_test() {
+ iterator.empty()
+ |> iterator.to_list
+ |> should.equal([])
+ }
-pub fn interleave_test() {
- iterator.from_list([1, 2, 3, 4])
- |> iterator.interleave(with: iterator.from_list([11, 12, 13, 14]))
- |> iterator.to_list
- |> should.equal([1, 11, 2, 12, 3, 13, 4, 14])
+ pub fn once_test() {
+ iterator.once(fn() { 1 })
+ |> iterator.to_list
+ |> should.equal([1])
+ }
- iterator.from_list([1, 2, 3, 4])
- |> iterator.interleave(with: iterator.from_list([100]))
- |> iterator.to_list
- |> should.equal([1, 100, 2, 3, 4])
+ pub fn single_test() {
+ iterator.single(1)
+ |> iterator.to_list
+ |> should.equal([1])
+ }
+
+ pub fn interleave_test() {
+ iterator.from_list([1, 2, 3, 4])
+ |> iterator.interleave(with: iterator.from_list([11, 12, 13, 14]))
+ |> iterator.to_list
+ |> should.equal([1, 11, 2, 12, 3, 13, 4, 14])
+
+ iterator.from_list([1, 2, 3, 4])
+ |> iterator.interleave(with: iterator.from_list([100]))
+ |> iterator.to_list
+ |> should.equal([1, 100, 2, 3, 4])
+ }
}
diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam
index c4f5ea3..bfe2c0b 100644
--- a/test/gleam/list_test.gleam
+++ b/test/gleam/list_test.gleam
@@ -1,724 +1,726 @@
-import gleam/should
-import gleam/list
-import gleam/int
-import gleam/float
-import gleam/string
-import gleam/pair
-
-pub fn length_test() {
- list.length([])
- |> should.equal(0)
-
- list.length([1])
- |> should.equal(1)
+if erlang {
+ import gleam/should
+ import gleam/list
+ import gleam/int
+ import gleam/float
+ import gleam/string
+ import gleam/pair
+
+ pub fn length_test() {
+ list.length([])
+ |> should.equal(0)
+
+ list.length([1])
+ |> should.equal(1)
+
+ list.length([1, 1])
+ |> should.equal(2)
+
+ list.length([1, 1, 1])
+ |> should.equal(3)
+ }
- list.length([1, 1])
- |> should.equal(2)
+ pub fn reverse_test() {
+ list.reverse([])
+ |> should.equal([])
+ list.reverse([1, 2, 3, 4, 5])
+ |> should.equal([5, 4, 3, 2, 1])
+ }
- list.length([1, 1, 1])
- |> should.equal(3)
-}
+ pub fn is_empty_test() {
+ list.is_empty([])
+ |> should.be_true
+ list.is_empty([1])
+ |> should.be_false
+ }
-pub fn reverse_test() {
- list.reverse([])
- |> should.equal([])
- list.reverse([1, 2, 3, 4, 5])
- |> should.equal([5, 4, 3, 2, 1])
-}
+ pub fn contains_test() {
+ list.contains([0, 4, 5, 1], 1)
+ |> should.be_true
+ list.contains([0, 4, 5, 7], 1)
+ |> should.be_false
+ list.contains([], 1)
+ |> should.be_false
+ }
-pub fn is_empty_test() {
- list.is_empty([])
- |> should.be_true
- list.is_empty([1])
- |> should.be_false
-}
+ pub fn head_test() {
+ list.head([0, 4, 5, 7])
+ |> should.equal(Ok(0))
-pub fn contains_test() {
- list.contains([0, 4, 5, 1], 1)
- |> should.be_true
- list.contains([0, 4, 5, 7], 1)
- |> should.be_false
- list.contains([], 1)
- |> should.be_false
-}
+ list.head([])
+ |> should.equal(Error(Nil))
+ }
-pub fn head_test() {
- list.head([0, 4, 5, 7])
- |> should.equal(Ok(0))
+ pub fn tail_test() {
+ list.tail([0, 4, 5, 7])
+ |> should.equal(Ok([4, 5, 7]))
- list.head([])
- |> should.equal(Error(Nil))
-}
+ list.tail([0])
+ |> should.equal(Ok([]))
-pub fn tail_test() {
- list.tail([0, 4, 5, 7])
- |> should.equal(Ok([4, 5, 7]))
+ list.tail([])
+ |> should.equal(Error(Nil))
+ }
- list.tail([0])
- |> should.equal(Ok([]))
+ pub fn filter_test() {
+ []
+ |> list.filter(fn(_) { True })
+ |> should.equal([])
- list.tail([])
- |> should.equal(Error(Nil))
-}
+ [0, 4, 5, 7, 3]
+ |> list.filter(fn(_) { True })
+ |> should.equal([0, 4, 5, 7, 3])
-pub fn filter_test() {
- []
- |> list.filter(fn(_) { True })
- |> should.equal([])
+ [0, 4, 5, 7, 3]
+ |> list.filter(fn(x) { x > 4 })
+ |> should.equal([5, 7])
- [0, 4, 5, 7, 3]
- |> list.filter(fn(_) { True })
- |> should.equal([0, 4, 5, 7, 3])
+ [0, 4, 5, 7, 3]
+ |> list.filter(fn(x) { x < 4 })
+ |> should.equal([0, 3])
+ }
- [0, 4, 5, 7, 3]
- |> list.filter(fn(x) { x > 4 })
- |> should.equal([5, 7])
+ pub fn filter_map_test() {
+ [2, 4, 6, 1]
+ |> list.filter_map(fn(x) { Ok(x + 1) })
+ |> should.equal([3, 5, 7, 2])
- [0, 4, 5, 7, 3]
- |> list.filter(fn(x) { x < 4 })
- |> should.equal([0, 3])
-}
+ [2, 4, 6, 1]
+ |> list.filter_map(Error)
+ |> should.equal([])
+ }
-pub fn filter_map_test() {
- [2, 4, 6, 1]
- |> list.filter_map(fn(x) { Ok(x + 1) })
- |> should.equal([3, 5, 7, 2])
+ pub fn map_test() {
+ []
+ |> list.map(fn(x) { x * 2 })
+ |> should.equal([])
- [2, 4, 6, 1]
- |> list.filter_map(Error)
- |> should.equal([])
-}
+ [0, 4, 5, 7, 3]
+ |> list.map(fn(x) { x * 2 })
+ |> should.equal([0, 8, 10, 14, 6])
+ }
-pub fn map_test() {
- []
- |> list.map(fn(x) { x * 2 })
- |> should.equal([])
+ pub fn map_fold_test() {
+ [1, 2, 3, 4]
+ |> list.map_fold(from: 0, with: fn(i, acc) { #(i * 2, acc + i) })
+ |> should.equal(#([2, 4, 6, 8], 10))
+ }
- [0, 4, 5, 7, 3]
- |> list.map(fn(x) { x * 2 })
- |> should.equal([0, 8, 10, 14, 6])
-}
+ pub fn try_map_test() {
+ let fun = fn(x) {
+ case x == 6 || x == 5 || x == 4 {
+ True -> Ok(x * 2)
+ False -> Error(x)
+ }
+ }
-pub fn map_fold_test() {
- [1, 2, 3, 4]
- |> list.map_fold(from: 0, with: fn(i, acc) { #(i * 2, acc + i) })
- |> should.equal(#([2, 4, 6, 8], 10))
-}
+ [5, 6, 5, 6]
+ |> list.try_map(fun)
+ |> should.equal(Ok([10, 12, 10, 12]))
-pub fn try_map_test() {
- let fun = fn(x) {
- case x == 6 || x == 5 || x == 4 {
- True -> Ok(x * 2)
- False -> Error(x)
- }
+ [4, 6, 5, 7, 3]
+ |> list.try_map(fun)
+ |> should.equal(Error(7))
}
- [5, 6, 5, 6]
- |> list.try_map(fun)
- |> should.equal(Ok([10, 12, 10, 12]))
-
- [4, 6, 5, 7, 3]
- |> list.try_map(fun)
- |> should.equal(Error(7))
-}
+ pub fn drop_test() {
+ []
+ |> list.drop(5)
+ |> should.equal([])
-pub fn drop_test() {
- []
- |> list.drop(5)
- |> should.equal([])
+ [1, 2, 3, 4, 5, 6, 7, 8]
+ |> list.drop(5)
+ |> should.equal([6, 7, 8])
+ }
- [1, 2, 3, 4, 5, 6, 7, 8]
- |> list.drop(5)
- |> should.equal([6, 7, 8])
-}
+ pub fn take_test() {
+ []
+ |> list.take(5)
+ |> should.equal([])
+ [1, 2, 3, 4, 5, 6, 7, 8]
+ |> list.take(5)
+ |> should.equal([1, 2, 3, 4, 5])
+ }
-pub fn take_test() {
- []
- |> list.take(5)
- |> should.equal([])
- [1, 2, 3, 4, 5, 6, 7, 8]
- |> list.take(5)
- |> should.equal([1, 2, 3, 4, 5])
-}
+ pub fn new_test() {
+ list.new()
+ |> should.equal([])
+ }
-pub fn new_test() {
- list.new()
- |> should.equal([])
-}
+ pub fn append_test() {
+ list.append([1], [2, 3])
+ |> should.equal([1, 2, 3])
+ }
-pub fn append_test() {
- list.append([1], [2, 3])
- |> should.equal([1, 2, 3])
-}
+ pub fn flatten_test() {
+ list.flatten([])
+ |> should.equal([])
-pub fn flatten_test() {
- list.flatten([])
- |> should.equal([])
+ list.flatten([[]])
+ |> should.equal([])
- list.flatten([[]])
- |> should.equal([])
+ list.flatten([[], [], []])
+ |> should.equal([])
- list.flatten([[], [], []])
- |> should.equal([])
+ list.flatten([[1, 2], [], [3, 4]])
+ |> should.equal([1, 2, 3, 4])
+ }
- list.flatten([[1, 2], [], [3, 4]])
- |> should.equal([1, 2, 3, 4])
-}
+ pub fn flat_map_test() {
+ list.flat_map([1, 10, 20], fn(x) { [x, x + 1] })
+ |> should.equal([1, 2, 10, 11, 20, 21])
+ }
-pub fn flat_map_test() {
- list.flat_map([1, 10, 20], fn(x) { [x, x + 1] })
- |> should.equal([1, 2, 10, 11, 20, 21])
-}
+ pub fn fold_test() {
+ [1, 2, 3]
+ |> list.fold([], fn(x, acc) { [x, ..acc] })
+ |> should.equal([3, 2, 1])
+ }
-pub fn fold_test() {
- [1, 2, 3]
- |> list.fold([], fn(x, acc) { [x, ..acc] })
- |> should.equal([3, 2, 1])
-}
+ pub fn fold_right_test() {
+ [1, 2, 3]
+ |> list.fold_right(from: [], with: fn(x, acc) { [x, ..acc] })
+ |> should.equal([1, 2, 3])
+ }
-pub fn fold_right_test() {
- [1, 2, 3]
- |> list.fold_right(from: [], with: fn(x, acc) { [x, ..acc] })
- |> should.equal([1, 2, 3])
-}
+ pub fn index_fold_test() {
+ ["a", "b", "c"]
+ |> list.index_fold([], fn(ix, i, acc) { [#(ix, i), ..acc] })
+ |> should.equal([#(2, "c"), #(1, "b"), #(0, "a")])
+ }
-pub fn index_fold_test() {
- ["a", "b", "c"]
- |> list.index_fold([], fn(ix, i, acc) { [#(ix, i), ..acc] })
- |> should.equal([#(2, "c"), #(1, "b"), #(0, "a")])
-}
+ pub fn fold_until_test() {
+ [1, 2, 3, 4]
+ |> list.fold_until(
+ from: 0,
+ with: fn(n, acc) {
+ case n < 4 {
+ True -> list.Continue(acc + n)
+ False -> list.Stop(acc)
+ }
+ },
+ )
+ |> should.equal(6)
+ }
-pub fn fold_until_test() {
- [1, 2, 3, 4]
- |> list.fold_until(
- from: 0,
- with: fn(n, acc) {
- case n < 4 {
- True -> list.Continue(acc + n)
- False -> list.Stop(acc)
- }
- },
- )
- |> should.equal(6)
-}
+ pub fn try_fold_test() {
+ [1, 2, 3]
+ |> list.try_fold(
+ 0,
+ fn(i, acc) {
+ case i < 4 {
+ True -> Ok(acc + i)
+ False -> Error(Nil)
+ }
+ },
+ )
+ |> should.equal(Ok(6))
+
+ [1, 2, 3]
+ |> list.try_fold(
+ 0,
+ fn(i, acc) {
+ case i < 3 {
+ True -> Ok(acc + i)
+ False -> Error(Nil)
+ }
+ },
+ )
+ |> should.equal(Error(Nil))
+ }
-pub fn try_fold_test() {
- [1, 2, 3]
- |> list.try_fold(
- 0,
- fn(i, acc) {
- case i < 4 {
- True -> Ok(acc + i)
- False -> Error(Nil)
- }
- },
- )
- |> should.equal(Ok(6))
-
- [1, 2, 3]
- |> list.try_fold(
- 0,
- fn(i, acc) {
- case i < 3 {
- True -> Ok(acc + i)
- False -> Error(Nil)
+ pub fn find_map_test() {
+ let f = fn(x) {
+ case x {
+ 2 -> Ok(4)
+ _ -> Error(Nil)
}
- },
- )
- |> should.equal(Error(Nil))
-}
-
-pub fn find_map_test() {
- let f = fn(x) {
- case x {
- 2 -> Ok(4)
- _ -> Error(Nil)
}
- }
- [1, 2, 3]
- |> list.find_map(with: f)
- |> should.equal(Ok(4))
+ [1, 2, 3]
+ |> list.find_map(with: f)
+ |> should.equal(Ok(4))
- [1, 3, 2]
- |> list.find_map(with: f)
- |> should.equal(Ok(4))
+ [1, 3, 2]
+ |> list.find_map(with: f)
+ |> should.equal(Ok(4))
- [1, 3]
- |> list.find_map(with: f)
- |> should.equal(Error(Nil))
-}
+ [1, 3]
+ |> list.find_map(with: f)
+ |> should.equal(Error(Nil))
+ }
-pub fn find_test() {
- let is_two = fn(x) { x == 2 }
+ pub fn find_test() {
+ let is_two = fn(x) { x == 2 }
- [1, 2, 3]
- |> list.find(one_that: is_two)
- |> should.equal(Ok(2))
+ [1, 2, 3]
+ |> list.find(one_that: is_two)
+ |> should.equal(Ok(2))
- [1, 3, 2]
- |> list.find(one_that: is_two)
- |> should.equal(Ok(2))
+ [1, 3, 2]
+ |> list.find(one_that: is_two)
+ |> should.equal(Ok(2))
- [1, 3]
- |> list.find(one_that: is_two)
- |> should.equal(Error(Nil))
-}
+ [1, 3]
+ |> list.find(one_that: is_two)
+ |> should.equal(Error(Nil))
+ }
-pub fn all_test() {
- list.all([1, 2, 3, 4, 5], fn(x) { x > 0 })
- |> should.equal(True)
+ pub fn all_test() {
+ list.all([1, 2, 3, 4, 5], fn(x) { x > 0 })
+ |> should.equal(True)
- list.all([1, 2, 3, 4, 5], fn(x) { x < 0 })
- |> should.equal(False)
+ list.all([1, 2, 3, 4, 5], fn(x) { x < 0 })
+ |> should.equal(False)
- list.all([], fn(_) { False })
- |> should.equal(True)
-}
+ list.all([], fn(_) { False })
+ |> should.equal(True)
+ }
-pub fn any_test() {
- list.any([1, 2, 3, 4, 5], fn(x) { x == 2 })
- |> should.equal(True)
+ pub fn any_test() {
+ list.any([1, 2, 3, 4, 5], fn(x) { x == 2 })
+ |> should.equal(True)
- list.any([1, 2, 3, 4, 5], fn(x) { x < 0 })
- |> should.equal(False)
+ list.any([1, 2, 3, 4, 5], fn(x) { x < 0 })
+ |> should.equal(False)
- list.any([], fn(_) { False })
- |> should.equal(False)
-}
+ list.any([], fn(_) { False })
+ |> should.equal(False)
+ }
-pub fn zip_test() {
- list.zip([], [1, 2, 3])
- |> should.equal([])
+ pub fn zip_test() {
+ list.zip([], [1, 2, 3])
+ |> should.equal([])
- list.zip([1, 2], [])
- |> should.equal([])
+ list.zip([1, 2], [])
+ |> should.equal([])
- list.zip([1, 2, 3], [4, 5, 6])
- |> should.equal([#(1, 4), #(2, 5), #(3, 6)])
+ list.zip([1, 2, 3], [4, 5, 6])
+ |> should.equal([#(1, 4), #(2, 5), #(3, 6)])
- list.zip([5, 6], [1, 2, 3])
- |> should.equal([#(5, 1), #(6, 2)])
+ list.zip([5, 6], [1, 2, 3])
+ |> should.equal([#(5, 1), #(6, 2)])
- list.zip([5, 6, 7], [1, 2])
- |> should.equal([#(5, 1), #(6, 2)])
-}
+ list.zip([5, 6, 7], [1, 2])
+ |> should.equal([#(5, 1), #(6, 2)])
+ }
-pub fn strict_zip_test() {
- list.strict_zip([], [1, 2, 3])
- |> should.equal(Error(list.LengthMismatch))
+ pub fn strict_zip_test() {
+ list.strict_zip([], [1, 2, 3])
+ |> should.equal(Error(list.LengthMismatch))
- list.strict_zip([1, 2], [])
- |> should.equal(Error(list.LengthMismatch))
+ list.strict_zip([1, 2], [])
+ |> should.equal(Error(list.LengthMismatch))
- list.strict_zip([1, 2, 3], [4, 5, 6])
- |> should.equal(Ok([#(1, 4), #(2, 5), #(3, 6)]))
+ list.strict_zip([1, 2, 3], [4, 5, 6])
+ |> should.equal(Ok([#(1, 4), #(2, 5), #(3, 6)]))
- list.strict_zip([5, 6], [1, 2, 3])
- |> should.equal(Error(list.LengthMismatch))
+ list.strict_zip([5, 6], [1, 2, 3])
+ |> should.equal(Error(list.LengthMismatch))
- list.strict_zip([5, 6, 7], [1, 2])
- |> should.equal(Error(list.LengthMismatch))
-}
+ list.strict_zip([5, 6, 7], [1, 2])
+ |> should.equal(Error(list.LengthMismatch))
+ }
-pub fn unzip_test() {
- list.unzip([#(1, 2), #(3, 4)])
- |> should.equal(#([1, 3], [2, 4]))
+ pub fn unzip_test() {
+ list.unzip([#(1, 2), #(3, 4)])
+ |> should.equal(#([1, 3], [2, 4]))
- list.unzip([])
- |> should.equal(#([], []))
-}
+ list.unzip([])
+ |> should.equal(#([], []))
+ }
-pub fn intersperse_test() {
- list.intersperse([1, 2, 3], 4)
- |> should.equal([1, 4, 2, 4, 3])
+ pub fn intersperse_test() {
+ list.intersperse([1, 2, 3], 4)
+ |> should.equal([1, 4, 2, 4, 3])
- list.intersperse([], 2)
- |> should.equal([])
-}
+ list.intersperse([], 2)
+ |> should.equal([])
+ }
-pub fn at_test() {
- list.at([1, 2, 3], 2)
- |> should.equal(Ok(3))
+ pub fn at_test() {
+ list.at([1, 2, 3], 2)
+ |> should.equal(Ok(3))
- list.at([1, 2, 3], 5)
- |> should.equal(Error(Nil))
+ list.at([1, 2, 3], 5)
+ |> should.equal(Error(Nil))
- list.at([], 0)
- |> should.equal(Error(Nil))
+ list.at([], 0)
+ |> should.equal(Error(Nil))
- list.at([1, 2, 3, 4, 5, 6], -1)
- |> should.equal(Error(Nil))
-}
+ list.at([1, 2, 3, 4, 5, 6], -1)
+ |> should.equal(Error(Nil))
+ }
-pub fn unique_test() {
- list.unique([1, 1, 2, 3, 4, 4, 4, 5, 6])
- |> should.equal([1, 2, 3, 4, 5, 6])
+ pub fn unique_test() {
+ list.unique([1, 1, 2, 3, 4, 4, 4, 5, 6])
+ |> should.equal([1, 2, 3, 4, 5, 6])
- list.unique([7, 1, 45, 6, 2, 47, 2, 7, 5])
- |> should.equal([7, 1, 45, 6, 2, 47, 5])
+ list.unique([7, 1, 45, 6, 2, 47, 2, 7, 5])
+ |> should.equal([7, 1, 45, 6, 2, 47, 5])
- list.unique([3, 4, 5])
- |> should.equal([3, 4, 5])
+ list.unique([3, 4, 5])
+ |> should.equal([3, 4, 5])
- list.unique([])
- |> should.equal([])
-}
+ list.unique([])
+ |> should.equal([])
+ }
-pub fn sort_test() {
- [4, 3, 6, 5, 4]
- |> list.sort(int.compare)
- |> should.equal([3, 4, 4, 5, 6])
+ pub fn sort_test() {
+ [4, 3, 6, 5, 4]
+ |> list.sort(int.compare)
+ |> should.equal([3, 4, 4, 5, 6])
- [4, 3, 6, 5, 4, 1]
- |> list.sort(int.compare)
- |> should.equal([1, 3, 4, 4, 5, 6])
+ [4, 3, 6, 5, 4, 1]
+ |> list.sort(int.compare)
+ |> should.equal([1, 3, 4, 4, 5, 6])
- [4.1, 3.1, 6.1, 5.1, 4.1]
- |> list.sort(float.compare)
- |> should.equal([3.1, 4.1, 4.1, 5.1, 6.1])
+ [4.1, 3.1, 6.1, 5.1, 4.1]
+ |> list.sort(float.compare)
+ |> should.equal([3.1, 4.1, 4.1, 5.1, 6.1])
- []
- |> list.sort(int.compare)
- |> should.equal([])
-}
+ []
+ |> list.sort(int.compare)
+ |> should.equal([])
+ }
-pub fn index_map_test() {
- list.index_map([3, 4, 5], fn(i, x) { #(i, x) })
- |> should.equal([#(0, 3), #(1, 4), #(2, 5)])
+ pub fn index_map_test() {
+ list.index_map([3, 4, 5], fn(i, x) { #(i, x) })
+ |> should.equal([#(0, 3), #(1, 4), #(2, 5)])
- let f = fn(i, x) { string.append(x, int.to_string(i)) }
- list.index_map(["a", "b", "c"], f)
- |> should.equal(["a0", "b1", "c2"])
-}
+ let f = fn(i, x) { string.append(x, int.to_string(i)) }
+ list.index_map(["a", "b", "c"], f)
+ |> should.equal(["a0", "b1", "c2"])
+ }
-pub fn range_test() {
- list.range(0, 0)
- |> should.equal([])
+ pub fn range_test() {
+ list.range(0, 0)
+ |> should.equal([])
- list.range(1, 1)
- |> should.equal([])
+ list.range(1, 1)
+ |> should.equal([])
- list.range(-1, -1)
- |> should.equal([])
+ list.range(-1, -1)
+ |> should.equal([])
- list.range(0, 1)
- |> should.equal([0])
+ list.range(0, 1)
+ |> should.equal([0])
- list.range(0, 5)
- |> should.equal([0, 1, 2, 3, 4])
+ list.range(0, 5)
+ |> should.equal([0, 1, 2, 3, 4])
- list.range(1, -5)
- |> should.equal([1, 0, -1, -2, -3, -4])
-}
+ list.range(1, -5)
+ |> should.equal([1, 0, -1, -2, -3, -4])
+ }
-pub fn repeat_test() {
- list.repeat(1, -10)
- |> should.equal([])
+ pub fn repeat_test() {
+ list.repeat(1, -10)
+ |> should.equal([])
- list.repeat(1, 0)
- |> should.equal([])
+ list.repeat(1, 0)
+ |> should.equal([])
- list.repeat(2, 3)
- |> should.equal([2, 2, 2])
+ list.repeat(2, 3)
+ |> should.equal([2, 2, 2])
- list.repeat("x", 5)
- |> should.equal(["x", "x", "x", "x", "x"])
-}
+ list.repeat("x", 5)
+ |> should.equal(["x", "x", "x", "x", "x"])
+ }
-pub fn split_test() {
- []
- |> list.split(0)
- |> should.equal(#([], []))
+ pub fn split_test() {
+ []
+ |> list.split(0)
+ |> should.equal(#([], []))
- [0, 1, 2, 3, 4]
- |> list.split(0)
- |> should.equal(#([], [0, 1, 2, 3, 4]))
+ [0, 1, 2, 3, 4]
+ |> list.split(0)
+ |> should.equal(#([], [0, 1, 2, 3, 4]))
- [0, 1, 2, 3, 4]
- |> list.split(-2)
- |> should.equal(#([], [0, 1, 2, 3, 4]))
+ [0, 1, 2, 3, 4]
+ |> list.split(-2)
+ |> should.equal(#([], [0, 1, 2, 3, 4]))
- [0, 1, 2, 3, 4]
- |> list.split(1)
- |> should.equal(#([0], [1, 2, 3, 4]))
+ [0, 1, 2, 3, 4]
+ |> list.split(1)
+ |> should.equal(#([0], [1, 2, 3, 4]))
- [0, 1, 2, 3, 4]
- |> list.split(3)
- |> should.equal(#([0, 1, 2], [3, 4]))
+ [0, 1, 2, 3, 4]
+ |> list.split(3)
+ |> should.equal(#([0, 1, 2], [3, 4]))
- [0, 1, 2, 3, 4]
- |> list.split(9)
- |> should.equal(#([0, 1, 2, 3, 4], []))
-}
+ [0, 1, 2, 3, 4]
+ |> list.split(9)
+ |> should.equal(#([0, 1, 2, 3, 4], []))
+ }
-pub fn split_while_test() {
- []
- |> list.split_while(fn(x) { x <= 5 })
- |> should.equal(#([], []))
+ pub fn split_while_test() {
+ []
+ |> list.split_while(fn(x) { x <= 5 })
+ |> should.equal(#([], []))
- [1, 2, 3, 4, 5]
- |> list.split_while(fn(x) { x <= 5 })
- |> should.equal(#([1, 2, 3, 4, 5], []))
+ [1, 2, 3, 4, 5]
+ |> list.split_while(fn(x) { x <= 5 })
+ |> should.equal(#([1, 2, 3, 4, 5], []))
- [1, 2, 3, 4, 5]
- |> list.split_while(fn(x) { x == 2 })
- |> should.equal(#([], [1, 2, 3, 4, 5]))
+ [1, 2, 3, 4, 5]
+ |> list.split_while(fn(x) { x == 2 })
+ |> should.equal(#([], [1, 2, 3, 4, 5]))
- [1, 2, 3, 4, 5]
- |> list.split_while(fn(x) { x <= 3 })
- |> should.equal(#([1, 2, 3], [4, 5]))
+ [1, 2, 3, 4, 5]
+ |> list.split_while(fn(x) { x <= 3 })
+ |> should.equal(#([1, 2, 3], [4, 5]))
- [1, 2, 3, 4, 5]
- |> list.split_while(fn(x) { x <= -3 })
- |> should.equal(#([], [1, 2, 3, 4, 5]))
-}
+ [1, 2, 3, 4, 5]
+ |> list.split_while(fn(x) { x <= -3 })
+ |> should.equal(#([], [1, 2, 3, 4, 5]))
+ }
-pub fn key_find_test() {
- let proplist = [#(0, "1"), #(1, "2")]
+ pub fn key_find_test() {
+ let proplist = [#(0, "1"), #(1, "2")]
- proplist
- |> list.key_find(0)
- |> should.equal(Ok("1"))
+ proplist
+ |> list.key_find(0)
+ |> should.equal(Ok("1"))
- proplist
- |> list.key_find(1)
- |> should.equal(Ok("2"))
+ proplist
+ |> list.key_find(1)
+ |> should.equal(Ok("2"))
- proplist
- |> list.key_find(2)
- |> should.equal(Error(Nil))
-}
+ proplist
+ |> list.key_find(2)
+ |> should.equal(Error(Nil))
+ }
-pub fn pop_test() {
- list.pop([1, 2, 3], fn(x) { x > 2 })
- |> should.equal(Ok(#(3, [1, 2])))
+ pub fn pop_test() {
+ list.pop([1, 2, 3], fn(x) { x > 2 })
+ |> should.equal(Ok(#(3, [1, 2])))
- list.pop([1, 2, 3], fn(x) { x > 4 })
- |> should.equal(Error(Nil))
+ list.pop([1, 2, 3], fn(x) { x > 4 })
+ |> should.equal(Error(Nil))
- list.pop([], fn(_x) { True })
- |> should.equal(Error(Nil))
-}
+ list.pop([], fn(_x) { True })
+ |> should.equal(Error(Nil))
+ }
-pub fn pop_map_test() {
- list.pop_map(["foo", "2", "3"], int.parse)
- |> should.equal(Ok(#(2, ["foo", "3"])))
+ pub fn pop_map_test() {
+ list.pop_map(["foo", "2", "3"], int.parse)
+ |> should.equal(Ok(#(2, ["foo", "3"])))
- list.pop_map(["foo", "bar"], int.parse)
- |> should.equal(Error(Nil))
+ list.pop_map(["foo", "bar"], int.parse)
+ |> should.equal(Error(Nil))
- list.pop_map([], int.parse)
- |> should.equal(Error(Nil))
-}
+ list.pop_map([], int.parse)
+ |> should.equal(Error(Nil))
+ }
-pub fn key_pop_test() {
- list.key_pop([#("a", 0), #("b", 1)], "a")
- |> should.equal(Ok(#(0, [#("b", 1)])))
+ pub fn key_pop_test() {
+ list.key_pop([#("a", 0), #("b", 1)], "a")
+ |> should.equal(Ok(#(0, [#("b", 1)])))
- list.key_pop([#("a", 0), #("b", 1)], "b")
- |> should.equal(Ok(#(1, [#("a", 0)])))
+ list.key_pop([#("a", 0), #("b", 1)], "b")
+ |> should.equal(Ok(#(1, [#("a", 0)])))
- list.key_pop([#("a", 0), #("b", 1)], "c")
- |> should.equal(Error(Nil))
-}
+ list.key_pop([#("a", 0), #("b", 1)], "c")
+ |> should.equal(Error(Nil))
+ }
-pub fn key_set_test() {
- [#(5, 0), #(4, 1)]
- |> list.key_set(4, 100)
- |> should.equal([#(5, 0), #(4, 100)])
+ pub fn key_set_test() {
+ [#(5, 0), #(4, 1)]
+ |> list.key_set(4, 100)
+ |> should.equal([#(5, 0), #(4, 100)])
- [#(5, 0), #(4, 1)]
- |> list.key_set(1, 100)
- |> should.equal([#(5, 0), #(4, 1), #(1, 100)])
-}
+ [#(5, 0), #(4, 1)]
+ |> list.key_set(1, 100)
+ |> should.equal([#(5, 0), #(4, 1), #(1, 100)])
+ }
-pub fn partition_test() {
- [1, 2, 3, 4, 5, 6, 7]
- |> list.partition(int.is_odd)
- |> should.equal(#([1, 3, 5, 7], [2, 4, 6]))
-}
+ pub fn partition_test() {
+ [1, 2, 3, 4, 5, 6, 7]
+ |> list.partition(int.is_odd)
+ |> should.equal(#([1, 3, 5, 7], [2, 4, 6]))
+ }
-pub fn permutations_test() {
- [1, 2]
- |> list.permutations
- |> should.equal([[1, 2], [2, 1]])
-
- let expected = [
- [1, 2, 3],
- [1, 3, 2],
- [2, 1, 3],
- [2, 3, 1],
- [3, 1, 2],
- [3, 2, 1],
- ]
-
- [1, 2, 3]
- |> list.permutations
- |> should.equal(expected)
-
- ["a", "b"]
- |> list.permutations
- |> should.equal([["a", "b"], ["b", "a"]])
-}
+ pub fn permutations_test() {
+ [1, 2]
+ |> list.permutations
+ |> should.equal([[1, 2], [2, 1]])
+
+ let expected = [
+ [1, 2, 3],
+ [1, 3, 2],
+ [2, 1, 3],
+ [2, 3, 1],
+ [3, 1, 2],
+ [3, 2, 1],
+ ]
+
+ [1, 2, 3]
+ |> list.permutations
+ |> should.equal(expected)
+
+ ["a", "b"]
+ |> list.permutations
+ |> should.equal([["a", "b"], ["b", "a"]])
+ }
-pub fn window_test() {
- [1, 2, 3]
- |> list.window(by: 2)
- |> should.equal([[1, 2], [2, 3]])
+ pub fn window_test() {
+ [1, 2, 3]
+ |> list.window(by: 2)
+ |> should.equal([[1, 2], [2, 3]])
- [1, 2, 3]
- |> list.window(3)
- |> should.equal([[1, 2, 3]])
+ [1, 2, 3]
+ |> list.window(3)
+ |> should.equal([[1, 2, 3]])
- [1, 2, 3]
- |> list.window(4)
- |> should.equal([])
+ [1, 2, 3]
+ |> list.window(4)
+ |> should.equal([])
- [1, 2, 3, 4, 5]
- |> list.window(3)
- |> should.equal([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
-}
+ [1, 2, 3, 4, 5]
+ |> list.window(3)
+ |> should.equal([[1, 2, 3], [2, 3, 4], [3, 4, 5]])
+ }
-pub fn window_by_2_test() {
- [1, 2, 3, 4]
- |> list.window_by_2
- |> should.equal([#(1, 2), #(2, 3), #(3, 4)])
+ pub fn window_by_2_test() {
+ [1, 2, 3, 4]
+ |> list.window_by_2
+ |> should.equal([#(1, 2), #(2, 3), #(3, 4)])
- [1]
- |> list.window_by_2
- |> should.equal([])
-}
+ [1]
+ |> list.window_by_2
+ |> should.equal([])
+ }
-pub fn drop_while_test() {
- [1, 2, 3, 4]
- |> list.drop_while(fn(x) { x < 3 })
- |> should.equal([3, 4])
-}
+ pub fn drop_while_test() {
+ [1, 2, 3, 4]
+ |> list.drop_while(fn(x) { x < 3 })
+ |> should.equal([3, 4])
+ }
-pub fn take_while_test() {
- [1, 2, 3, 2, 4]
- |> list.take_while(fn(x) { x < 3 })
- |> should.equal([1, 2])
-}
+ pub fn take_while_test() {
+ [1, 2, 3, 2, 4]
+ |> list.take_while(fn(x) { x < 3 })
+ |> should.equal([1, 2])
+ }
-pub fn chunk_test() {
- [1, 2, 2, 3, 4, 4, 6, 7, 7]
- |> list.chunk(by: fn(n) { n % 2 })
- |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]])
-}
+ pub fn chunk_test() {
+ [1, 2, 2, 3, 4, 4, 6, 7, 7]
+ |> list.chunk(by: fn(n) { n % 2 })
+ |> should.equal([[1], [2, 2], [3], [4, 4, 6], [7, 7]])
+ }
-pub fn sized_chunk_test() {
- [1, 2, 3, 4, 5, 6]
- |> list.sized_chunk(into: 2)
- |> should.equal([[1, 2], [3, 4], [5, 6]])
+ pub fn sized_chunk_test() {
+ [1, 2, 3, 4, 5, 6]
+ |> list.sized_chunk(into: 2)
+ |> should.equal([[1, 2], [3, 4], [5, 6]])
- [1, 2, 3, 4, 5, 6, 7, 8]
- |> list.sized_chunk(into: 3)
- |> should.equal([[1, 2, 3], [4, 5, 6], [7, 8]])
-}
+ [1, 2, 3, 4, 5, 6, 7, 8]
+ |> list.sized_chunk(into: 3)
+ |> should.equal([[1, 2, 3], [4, 5, 6], [7, 8]])
+ }
-pub fn reduce_test() {
- []
- |> list.reduce(with: fn(x, y) { x + y })
- |> should.equal(Error(Nil))
+ pub fn reduce_test() {
+ []
+ |> list.reduce(with: fn(x, y) { x + y })
+ |> should.equal(Error(Nil))
- [1, 2, 3, 4, 5]
- |> list.reduce(with: fn(x, y) { x + y })
- |> should.equal(Ok(15))
-}
+ [1, 2, 3, 4, 5]
+ |> list.reduce(with: fn(x, y) { x + y })
+ |> should.equal(Ok(15))
+ }
-pub fn scan_test() {
- []
- |> list.scan(from: 0, with: fn(i, acc) { i + acc })
- |> should.equal([])
-
- [1, 2, 3, 4]
- |> list.scan(from: 0, with: fn(i, acc) { 2 * i + acc })
- |> should.equal([2, 6, 12, 20])
-
- [1, 2, 3, 4]
- |> list.scan(
- from: "",
- with: fn(i, acc) {
- case int.is_even(i) {
- True -> "Even"
- False -> "Odd"
- }
- |> string.append(acc, _)
- },
- )
- |> should.equal(["Odd", "OddEven", "OddEvenOdd", "OddEvenOddEven"])
-}
+ pub fn scan_test() {
+ []
+ |> list.scan(from: 0, with: fn(i, acc) { i + acc })
+ |> should.equal([])
+
+ [1, 2, 3, 4]
+ |> list.scan(from: 0, with: fn(i, acc) { 2 * i + acc })
+ |> should.equal([2, 6, 12, 20])
+
+ [1, 2, 3, 4]
+ |> list.scan(
+ from: "",
+ with: fn(i, acc) {
+ case int.is_even(i) {
+ True -> "Even"
+ False -> "Odd"
+ }
+ |> string.append(acc, _)
+ },
+ )
+ |> should.equal(["Odd", "OddEven", "OddEvenOdd", "OddEvenOddEven"])
+ }
-pub fn last_test() {
- list.last([])
- |> should.equal(Error(Nil))
+ pub fn last_test() {
+ list.last([])
+ |> should.equal(Error(Nil))
- list.last([1, 2, 3, 4, 5])
- |> should.equal(Ok(5))
-}
+ list.last([1, 2, 3, 4, 5])
+ |> should.equal(Ok(5))
+ }
-pub fn combinations_test() {
- list.combinations([1, 2, 3], by: 0)
- |> should.equal([[]])
+ pub fn combinations_test() {
+ list.combinations([1, 2, 3], by: 0)
+ |> should.equal([[]])
- list.combinations([1, 2, 3], by: 1)
- |> should.equal([[1], [2], [3]])
+ list.combinations([1, 2, 3], by: 1)
+ |> should.equal([[1], [2], [3]])
- list.combinations([1, 2, 3], by: 2)
- |> should.equal([[1, 2], [1, 3], [2, 3]])
+ list.combinations([1, 2, 3], by: 2)
+ |> should.equal([[1, 2], [1, 3], [2, 3]])
- list.combinations([1, 2, 3], by: 3)
- |> should.equal([[1, 2, 3]])
+ list.combinations([1, 2, 3], by: 3)
+ |> should.equal([[1, 2, 3]])
- list.combinations([1, 2, 3], by: 4)
- |> should.equal([])
+ list.combinations([1, 2, 3], by: 4)
+ |> should.equal([])
- list.combinations([1, 2, 3, 4], 3)
- |> should.equal([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]])
-}
+ list.combinations([1, 2, 3, 4], 3)
+ |> should.equal([[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]])
+ }
-pub fn combination_pairs_test() {
- list.combination_pairs([1])
- |> should.equal([])
+ pub fn combination_pairs_test() {
+ list.combination_pairs([1])
+ |> should.equal([])
- list.combination_pairs([1, 2])
- |> should.equal([#(1, 2)])
+ list.combination_pairs([1, 2])
+ |> should.equal([#(1, 2)])
- list.combination_pairs([1, 2, 3])
- |> should.equal([#(1, 2), #(1, 3), #(2, 3)])
+ list.combination_pairs([1, 2, 3])
+ |> should.equal([#(1, 2), #(1, 3), #(2, 3)])
- list.combination_pairs([1, 2, 3, 4])
- |> should.equal([#(1, 2), #(1, 3), #(1, 4), #(2, 3), #(2, 4), #(3, 4)])
-}
+ list.combination_pairs([1, 2, 3, 4])
+ |> should.equal([#(1, 2), #(1, 3), #(1, 4), #(2, 3), #(2, 4), #(3, 4)])
+ }
-pub fn interleave_test() {
- list.interleave([[1, 2], [101, 102]])
- |> should.equal([1, 101, 2, 102])
+ pub fn interleave_test() {
+ list.interleave([[1, 2], [101, 102]])
+ |> should.equal([1, 101, 2, 102])
- list.interleave([[1, 2], [101, 102], [201, 202]])
- |> should.equal([1, 101, 201, 2, 102, 202])
+ list.interleave([[1, 2], [101, 102], [201, 202]])
+ |> should.equal([1, 101, 201, 2, 102, 202])
- // Left over elements are added at the end
- list.interleave([[1, 2, 3], [101, 102]])
- |> should.equal([1, 101, 2, 102, 3])
+ // Left over elements are added at the end
+ list.interleave([[1, 2, 3], [101, 102]])
+ |> should.equal([1, 101, 2, 102, 3])
- list.interleave([[1, 2], [101, 102, 103]])
- |> should.equal([1, 101, 2, 102, 103])
-}
+ list.interleave([[1, 2], [101, 102, 103]])
+ |> should.equal([1, 101, 2, 102, 103])
+ }
-pub fn transpose_test() {
- list.transpose([[1, 2, 3], [101, 102, 103]])
- |> should.equal([[1, 101], [2, 102], [3, 103]])
+ pub fn transpose_test() {
+ list.transpose([[1, 2, 3], [101, 102, 103]])
+ |> should.equal([[1, 101], [2, 102], [3, 103]])
- list.transpose([[1, 2, 3], [101, 102, 103], [201, 202, 203]])
- |> should.equal([[1, 101, 201], [2, 102, 202], [3, 103, 203]])
+ list.transpose([[1, 2, 3], [101, 102, 103], [201, 202, 203]])
+ |> should.equal([[1, 101, 201], [2, 102, 202], [3, 103, 203]])
- // Left over elements are still returned
- list.transpose([[1, 2], [101, 102, 103]])
- |> should.equal([[1, 101], [2, 102], [103]])
+ // Left over elements are still returned
+ list.transpose([[1, 2], [101, 102, 103]])
+ |> should.equal([[1, 101], [2, 102], [103]])
- list.transpose([[1, 2, 3], [101, 102], [201, 202, 203]])
- |> should.equal([[1, 101, 201], [2, 102, 202], [3, 203]])
+ list.transpose([[1, 2, 3], [101, 102], [201, 202, 203]])
+ |> should.equal([[1, 101, 201], [2, 102, 202], [3, 203]])
+ }
}
diff --git a/test/gleam/map_test.gleam b/test/gleam/map_test.gleam
index e393a7f..6f32c8f 100644
--- a/test/gleam/map_test.gleam
+++ b/test/gleam/map_test.gleam
@@ -1,169 +1,171 @@
-import gleam/string
-import gleam/should
-import gleam/map
-
-pub fn from_list_test() {
- [#(4, 0), #(1, 0)]
- |> map.from_list
- |> map.size
- |> should.equal(2)
-
- [#(1, 0), #(1, 1)]
- |> map.from_list
- |> should.equal(map.from_list([#(1, 1)]))
-}
+if erlang {
+ import gleam/string
+ import gleam/should
+ import gleam/map
+
+ pub fn from_list_test() {
+ [#(4, 0), #(1, 0)]
+ |> map.from_list
+ |> map.size
+ |> should.equal(2)
+
+ [#(1, 0), #(1, 1)]
+ |> map.from_list
+ |> should.equal(map.from_list([#(1, 1)]))
+ }
-pub fn has_key_test() {
- []
- |> map.from_list
- |> map.has_key(1)
- |> should.be_false
-
- [#(1, 0)]
- |> map.from_list
- |> map.has_key(1)
- |> should.be_true
-
- [#(4, 0), #(1, 0)]
- |> map.from_list
- |> map.has_key(1)
- |> should.be_true
-
- [#(4, 0), #(1, 0)]
- |> map.from_list
- |> map.has_key(0)
- |> should.be_false
-}
+ pub fn has_key_test() {
+ []
+ |> map.from_list
+ |> map.has_key(1)
+ |> should.be_false
+
+ [#(1, 0)]
+ |> map.from_list
+ |> map.has_key(1)
+ |> should.be_true
+
+ [#(4, 0), #(1, 0)]
+ |> map.from_list
+ |> map.has_key(1)
+ |> should.be_true
+
+ [#(4, 0), #(1, 0)]
+ |> map.from_list
+ |> map.has_key(0)
+ |> should.be_false
+ }
-pub fn new_test() {
- map.new()
- |> map.size
- |> should.equal(0)
+ pub fn new_test() {
+ map.new()
+ |> map.size
+ |> should.equal(0)
- map.new()
- |> map.to_list
- |> should.equal([])
-}
+ map.new()
+ |> map.to_list
+ |> should.equal([])
+ }
-pub fn get_test() {
- let proplist = [#(4, 0), #(1, 1)]
- let m = map.from_list(proplist)
+ pub fn get_test() {
+ let proplist = [#(4, 0), #(1, 1)]
+ let m = map.from_list(proplist)
- m
- |> map.get(4)
- |> should.equal(Ok(0))
+ m
+ |> map.get(4)
+ |> should.equal(Ok(0))
- m
- |> map.get(1)
- |> should.equal(Ok(1))
+ m
+ |> map.get(1)
+ |> should.equal(Ok(1))
- m
- |> map.get(2)
- |> should.equal(Error(Nil))
-}
+ m
+ |> map.get(2)
+ |> should.equal(Error(Nil))
+ }
-pub fn insert_test() {
- map.new()
- |> map.insert("a", 0)
- |> map.insert("b", 1)
- |> map.insert("c", 2)
- |> should.equal(map.from_list([#("a", 0), #("b", 1), #("c", 2)]))
-}
+ pub fn insert_test() {
+ map.new()
+ |> map.insert("a", 0)
+ |> map.insert("b", 1)
+ |> map.insert("c", 2)
+ |> should.equal(map.from_list([#("a", 0), #("b", 1), #("c", 2)]))
+ }
-pub fn map_values_test() {
- [#(1, 0), #(2, 1), #(3, 2)]
- |> map.from_list
- |> map.map_values(fn(k, v) { k + v })
- |> should.equal(map.from_list([#(1, 1), #(2, 3), #(3, 5)]))
-}
+ pub fn map_values_test() {
+ [#(1, 0), #(2, 1), #(3, 2)]
+ |> map.from_list
+ |> map.map_values(fn(k, v) { k + v })
+ |> should.equal(map.from_list([#(1, 1), #(2, 3), #(3, 5)]))
+ }
-pub fn keys_test() {
- [#("a", 0), #("b", 1), #("c", 2)]
- |> map.from_list
- |> map.keys
- |> should.equal(["a", "b", "c"])
-}
+ pub fn keys_test() {
+ [#("a", 0), #("b", 1), #("c", 2)]
+ |> map.from_list
+ |> map.keys
+ |> should.equal(["a", "b", "c"])
+ }
-pub fn values_test() {
- [#("a", 0), #("b", 1), #("c", 2)]
- |> map.from_list
- |> map.values
- |> should.equal([0, 1, 2])
-}
+ pub fn values_test() {
+ [#("a", 0), #("b", 1), #("c", 2)]
+ |> map.from_list
+ |> map.values
+ |> should.equal([0, 1, 2])
+ }
-pub fn take_test() {
- [#("a", 0), #("b", 1), #("c", 2)]
- |> map.from_list
- |> map.take(["a", "b", "d"])
- |> should.equal(map.from_list([#("a", 0), #("b", 1)]))
-}
+ pub fn take_test() {
+ [#("a", 0), #("b", 1), #("c", 2)]
+ |> map.from_list
+ |> map.take(["a", "b", "d"])
+ |> should.equal(map.from_list([#("a", 0), #("b", 1)]))
+ }
-pub fn drop_test() {
- [#("a", 0), #("b", 1), #("c", 2)]
- |> map.from_list
- |> map.drop(["a", "b", "d"])
- |> should.equal(map.from_list([#("c", 2)]))
-}
+ pub fn drop_test() {
+ [#("a", 0), #("b", 1), #("c", 2)]
+ |> map.from_list
+ |> map.drop(["a", "b", "d"])
+ |> should.equal(map.from_list([#("c", 2)]))
+ }
-pub fn merge_test() {
- let a = map.from_list([#("a", 2), #("c", 4), #("d", 3)])
+ pub fn merge_test() {
+ let a = map.from_list([#("a", 2), #("c", 4), #("d", 3)])
- let b = map.from_list([#("a", 0), #("b", 1), #("c", 2)])
+ let b = map.from_list([#("a", 0), #("b", 1), #("c", 2)])
- map.merge(a, b)
- |> should.equal(map.from_list([#("a", 0), #("b", 1), #("c", 2), #("d", 3)]))
+ map.merge(a, b)
+ |> should.equal(map.from_list([#("a", 0), #("b", 1), #("c", 2), #("d", 3)]))
- map.merge(b, a)
- |> should.equal(map.from_list([#("a", 2), #("b", 1), #("c", 4), #("d", 3)]))
-}
+ map.merge(b, a)
+ |> should.equal(map.from_list([#("a", 2), #("b", 1), #("c", 4), #("d", 3)]))
+ }
-pub fn delete_test() {
- [#("a", 0), #("b", 1), #("c", 2)]
- |> map.from_list
- |> map.delete("a")
- |> map.delete("d")
- |> should.equal(map.from_list([#("b", 1), #("c", 2)]))
-}
+ pub fn delete_test() {
+ [#("a", 0), #("b", 1), #("c", 2)]
+ |> map.from_list
+ |> map.delete("a")
+ |> map.delete("d")
+ |> should.equal(map.from_list([#("b", 1), #("c", 2)]))
+ }
-pub fn update_test() {
- let dict = map.from_list([#("a", 0), #("b", 1), #("c", 2)])
+ pub fn update_test() {
+ let dict = map.from_list([#("a", 0), #("b", 1), #("c", 2)])
- let inc_or_zero = fn(x) {
- case x {
- Ok(i) -> i + 1
- Error(_) -> 0
+ let inc_or_zero = fn(x) {
+ case x {
+ Ok(i) -> i + 1
+ Error(_) -> 0
+ }
}
- }
- dict
- |> map.update("a", inc_or_zero)
- |> should.equal(map.from_list([#("a", 1), #("b", 1), #("c", 2)]))
+ dict
+ |> map.update("a", inc_or_zero)
+ |> should.equal(map.from_list([#("a", 1), #("b", 1), #("c", 2)]))
- dict
- |> map.update("b", inc_or_zero)
- |> should.equal(map.from_list([#("a", 0), #("b", 2), #("c", 2)]))
+ dict
+ |> map.update("b", inc_or_zero)
+ |> should.equal(map.from_list([#("a", 0), #("b", 2), #("c", 2)]))
- dict
- |> map.update("z", inc_or_zero)
- |> should.equal(map.from_list([#("a", 0), #("b", 1), #("c", 2), #("z", 0)]))
-}
+ dict
+ |> map.update("z", inc_or_zero)
+ |> should.equal(map.from_list([#("a", 0), #("b", 1), #("c", 2), #("z", 0)]))
+ }
-pub fn fold_test() {
- let dict = map.from_list([#("a", 0), #("b", 1), #("c", 2), #("d", 3)])
+ pub fn fold_test() {
+ let dict = map.from_list([#("a", 0), #("b", 1), #("c", 2), #("d", 3)])
- let add = fn(_, v, acc) { v + acc }
+ let add = fn(_, v, acc) { v + acc }
- dict
- |> map.fold(0, add)
- |> should.equal(6)
+ dict
+ |> map.fold(0, add)
+ |> should.equal(6)
- let concat = fn(k, _, acc) { string.append(acc, k) }
+ let concat = fn(k, _, acc) { string.append(acc, k) }
- dict
- |> map.fold("", concat)
- |> should.equal("abcd")
+ dict
+ |> map.fold("", concat)
+ |> should.equal("abcd")
- map.from_list([])
- |> map.fold(0, add)
- |> should.equal(0)
+ map.from_list([])
+ |> map.fold(0, add)
+ |> should.equal(0)
+ }
}
diff --git a/test/gleam/option_test.gleam b/test/gleam/option_test.gleam
index 35c9eb3..32b1df6 100644
--- a/test/gleam/option_test.gleam
+++ b/test/gleam/option_test.gleam
@@ -1,115 +1,117 @@
-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])
+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])
+ }
}
diff --git a/test/gleam/order_test.gleam b/test/gleam/order_test.gleam
index 2517f9c..95cd6e8 100644
--- a/test/gleam/order_test.gleam
+++ b/test/gleam/order_test.gleam
@@ -1,111 +1,113 @@
-import gleam/should
-import gleam/order.{Eq, Gt, Lt}
+if erlang {
+ import gleam/should
+ import gleam/order.{Eq, Gt, Lt}
-pub fn reverse_test() {
- order.reverse(Lt)
- |> should.equal(Gt)
+ pub fn reverse_test() {
+ order.reverse(Lt)
+ |> should.equal(Gt)
- order.reverse(Eq)
- |> should.equal(Eq)
+ order.reverse(Eq)
+ |> should.equal(Eq)
- order.reverse(Gt)
- |> should.equal(Lt)
-}
+ order.reverse(Gt)
+ |> should.equal(Lt)
+ }
-pub fn to_int_test() {
- order.to_int(Lt)
- |> should.equal(-1)
+ pub fn to_int_test() {
+ order.to_int(Lt)
+ |> should.equal(-1)
- order.to_int(Eq)
- |> should.equal(0)
+ order.to_int(Eq)
+ |> should.equal(0)
- order.to_int(Gt)
- |> should.equal(1)
-}
+ order.to_int(Gt)
+ |> should.equal(1)
+ }
-pub fn compare_test() {
- order.compare(Lt, Lt)
- |> should.equal(Eq)
+ pub fn compare_test() {
+ order.compare(Lt, Lt)
+ |> should.equal(Eq)
- order.compare(Lt, Eq)
- |> should.equal(Lt)
+ order.compare(Lt, Eq)
+ |> should.equal(Lt)
- order.compare(Lt, Gt)
- |> should.equal(Lt)
+ order.compare(Lt, Gt)
+ |> should.equal(Lt)
- order.compare(Eq, Lt)
- |> should.equal(Gt)
+ order.compare(Eq, Lt)
+ |> should.equal(Gt)
- order.compare(Eq, Eq)
- |> should.equal(Eq)
+ order.compare(Eq, Eq)
+ |> should.equal(Eq)
- order.compare(Eq, Gt)
- |> should.equal(Lt)
+ order.compare(Eq, Gt)
+ |> should.equal(Lt)
- order.compare(Gt, Lt)
- |> should.equal(Gt)
+ order.compare(Gt, Lt)
+ |> should.equal(Gt)
- order.compare(Gt, Eq)
- |> should.equal(Gt)
+ order.compare(Gt, Eq)
+ |> should.equal(Gt)
- order.compare(Gt, Gt)
- |> should.equal(Eq)
-}
+ order.compare(Gt, Gt)
+ |> should.equal(Eq)
+ }
-pub fn max_test() {
- order.max(Lt, Lt)
- |> should.equal(Lt)
+ pub fn max_test() {
+ order.max(Lt, Lt)
+ |> should.equal(Lt)
- order.max(Lt, Eq)
- |> should.equal(Eq)
+ order.max(Lt, Eq)
+ |> should.equal(Eq)
- order.max(Lt, Gt)
- |> should.equal(Gt)
+ order.max(Lt, Gt)
+ |> should.equal(Gt)
- order.max(Eq, Lt)
- |> should.equal(Eq)
+ order.max(Eq, Lt)
+ |> should.equal(Eq)
- order.max(Eq, Eq)
- |> should.equal(Eq)
+ order.max(Eq, Eq)
+ |> should.equal(Eq)
- order.max(Eq, Gt)
- |> should.equal(Gt)
+ order.max(Eq, Gt)
+ |> should.equal(Gt)
- order.max(Gt, Lt)
- |> should.equal(Gt)
+ order.max(Gt, Lt)
+ |> should.equal(Gt)
- order.max(Gt, Eq)
- |> should.equal(Gt)
+ order.max(Gt, Eq)
+ |> should.equal(Gt)
- order.max(Gt, Gt)
- |> should.equal(Gt)
-}
+ order.max(Gt, Gt)
+ |> should.equal(Gt)
+ }
-pub fn min_test() {
- order.min(Lt, Lt)
- |> should.equal(Lt)
+ pub fn min_test() {
+ order.min(Lt, Lt)
+ |> should.equal(Lt)
- order.min(Lt, Eq)
- |> should.equal(Lt)
+ order.min(Lt, Eq)
+ |> should.equal(Lt)
- order.min(Lt, Gt)
- |> should.equal(Lt)
+ order.min(Lt, Gt)
+ |> should.equal(Lt)
- order.min(Eq, Lt)
- |> should.equal(Lt)
+ order.min(Eq, Lt)
+ |> should.equal(Lt)
- order.min(Eq, Eq)
- |> should.equal(Eq)
+ order.min(Eq, Eq)
+ |> should.equal(Eq)
- order.min(Eq, Gt)
- |> should.equal(Eq)
+ order.min(Eq, Gt)
+ |> should.equal(Eq)
- order.min(Gt, Lt)
- |> should.equal(Lt)
+ order.min(Gt, Lt)
+ |> should.equal(Lt)
- order.min(Gt, Eq)
- |> should.equal(Eq)
+ order.min(Gt, Eq)
+ |> should.equal(Eq)
- order.min(Gt, Gt)
- |> should.equal(Gt)
+ order.min(Gt, Gt)
+ |> should.equal(Gt)
+ }
}
diff --git a/test/gleam/os_test.gleam b/test/gleam/os_test.gleam
index 3442a90..b3d799d 100644
--- a/test/gleam/os_test.gleam
+++ b/test/gleam/os_test.gleam
@@ -1,47 +1,49 @@
-import gleam/map
-import gleam/os
-import gleam/io
-import gleam/should
+if erlang {
+ import gleam/map
+ import gleam/os
+ import gleam/io
+ import gleam/should
-pub fn env_test() {
- os.insert_env("GLEAM_TEST", "hello")
- os.get_env()
- |> map.get("GLEAM_TEST")
- |> should.equal(Ok("hello"))
+ pub fn env_test() {
+ os.insert_env("GLEAM_TEST", "hello")
+ os.get_env()
+ |> map.get("GLEAM_TEST")
+ |> should.equal(Ok("hello"))
- os.delete_env("GLEAM_TEST")
- os.get_env()
- |> map.get("GLEAM_TEST")
- |> should.equal(Error(Nil))
-}
+ os.delete_env("GLEAM_TEST")
+ os.get_env()
+ |> map.get("GLEAM_TEST")
+ |> should.equal(Error(Nil))
+ }
-pub fn unicode_test() {
- os.insert_env("GLEAM_UNICODE_TEST", "Iñtërnâtiônà£ißætiøn☃💩")
- os.get_env()
- |> map.get("GLEAM_UNICODE_TEST")
- |> should.equal(Ok("Iñtërnâtiônà£ißætiøn☃💩"))
-}
+ pub fn unicode_test() {
+ os.insert_env("GLEAM_UNICODE_TEST", "Iñtërnâtiônà£ißætiøn☃💩")
+ os.get_env()
+ |> map.get("GLEAM_UNICODE_TEST")
+ |> should.equal(Ok("Iñtërnâtiônà£ißætiøn☃💩"))
+ }
-pub fn system_time_test() {
- let june_12_2020 = 1591966971
- { os.system_time(os.Second) > june_12_2020 }
- |> should.equal(True)
- { os.system_time(os.Second) < june_12_2020 * 1000 }
- |> should.equal(True)
- { os.system_time(os.Millisecond) > june_12_2020 * 1000 }
- |> should.equal(True)
- { os.system_time(os.Millisecond) < june_12_2020 * 1000000 }
- |> should.equal(True)
-}
+ pub fn system_time_test() {
+ let june_12_2020 = 1591966971
+ { os.system_time(os.Second) > june_12_2020 }
+ |> should.equal(True)
+ { os.system_time(os.Second) < june_12_2020 * 1000 }
+ |> should.equal(True)
+ { os.system_time(os.Millisecond) > june_12_2020 * 1000 }
+ |> should.equal(True)
+ { os.system_time(os.Millisecond) < june_12_2020 * 1000000 }
+ |> should.equal(True)
+ }
-pub fn erlang_timestamp_test() {
- // in microseconds
- let june_12_2020 = 1591966971000000
- let #(mega_seconds, seconds, micro_seconds) = os.erlang_timestamp()
+ pub fn erlang_timestamp_test() {
+ // in microseconds
+ let june_12_2020 = 1591966971000000
+ let #(mega_seconds, seconds, micro_seconds) = os.erlang_timestamp()
- let stamp_as_micro =
- { mega_seconds * 1_000_000 + seconds } * 1_000_000 + micro_seconds
+ let stamp_as_micro =
+ { mega_seconds * 1_000_000 + seconds } * 1_000_000 + micro_seconds
- { stamp_as_micro > june_12_2020 }
- |> should.be_true()
+ { stamp_as_micro > june_12_2020 }
+ |> should.be_true()
+ }
}
diff --git a/test/gleam/pair_test.gleam b/test/gleam/pair_test.gleam
index 1950929..891ce4a 100644
--- a/test/gleam/pair_test.gleam
+++ b/test/gleam/pair_test.gleam
@@ -1,58 +1,60 @@
-import gleam/should
-import gleam/pair
-
-pub fn first_test() {
- #(1, 2)
- |> pair.first
- |> should.equal(1)
-
- #("abc", [])
- |> pair.first
- |> should.equal("abc")
-}
-
-pub fn second_test() {
- #(1, 2)
- |> pair.second
- |> should.equal(2)
-
- #("abc", [])
- |> pair.second
- |> should.equal([])
-}
-
-pub fn swap_test() {
- #(1, "2")
- |> pair.swap
- |> should.equal(#("2", 1))
-}
-
-pub fn map_first_test() {
- let inc = fn(a) { a + 1 }
- pair.map_first(#(1, 2), inc)
- |> should.equal(#(2, 2))
-
- pair.map_first(#(8, 2), inc)
- |> should.equal(#(9, 2))
-
- pair.map_first(#(0, -2), inc)
- |> should.equal(#(1, -2))
-
- pair.map_first(#(-10, 20), inc)
- |> should.equal(#(-9, 20))
-}
-
-pub fn map_second_test() {
- let dec = fn(a) { a - 1 }
- pair.map_second(#(1, 2), dec)
- |> should.equal(#(1, 1))
-
- pair.map_second(#(8, 2), dec)
- |> should.equal(#(8, 1))
-
- pair.map_second(#(0, -2), dec)
- |> should.equal(#(0, -3))
-
- pair.map_second(#(-10, 20), dec)
- |> should.equal(#(-10, 19))
+if erlang {
+ import gleam/should
+ import gleam/pair
+
+ pub fn first_test() {
+ #(1, 2)
+ |> pair.first
+ |> should.equal(1)
+
+ #("abc", [])
+ |> pair.first
+ |> should.equal("abc")
+ }
+
+ pub fn second_test() {
+ #(1, 2)
+ |> pair.second
+ |> should.equal(2)
+
+ #("abc", [])
+ |> pair.second
+ |> should.equal([])
+ }
+
+ pub fn swap_test() {
+ #(1, "2")
+ |> pair.swap
+ |> should.equal(#("2", 1))
+ }
+
+ pub fn map_first_test() {
+ let inc = fn(a) { a + 1 }
+ pair.map_first(#(1, 2), inc)
+ |> should.equal(#(2, 2))
+
+ pair.map_first(#(8, 2), inc)
+ |> should.equal(#(9, 2))
+
+ pair.map_first(#(0, -2), inc)
+ |> should.equal(#(1, -2))
+
+ pair.map_first(#(-10, 20), inc)
+ |> should.equal(#(-9, 20))
+ }
+
+ pub fn map_second_test() {
+ let dec = fn(a) { a - 1 }
+ pair.map_second(#(1, 2), dec)
+ |> should.equal(#(1, 1))
+
+ pair.map_second(#(8, 2), dec)
+ |> should.equal(#(8, 1))
+
+ pair.map_second(#(0, -2), dec)
+ |> should.equal(#(0, -3))
+
+ pair.map_second(#(-10, 20), dec)
+ |> should.equal(#(-10, 19))
+ }
}
diff --git a/test/gleam/queue_test.gleam b/test/gleam/queue_test.gleam
index ae5dfeb..24c70b1 100644
--- a/test/gleam/queue_test.gleam
+++ b/test/gleam/queue_test.gleam
@@ -1,332 +1,334 @@
-import gleam/queue
-import gleam/int
-import gleam/list
-import gleam/should
-import gleam/pair
-
-pub fn from_and_to_list_test() {
- queue.from_list([])
- |> should.equal(queue.new())
-
- [1, 2, 3]
- |> queue.from_list
- |> queue.to_list
- |> should.equal([1, 2, 3])
-}
-
-pub fn is_empty_test() {
- queue.new()
- |> queue.is_empty
- |> should.be_true
+if erlang {
+ import gleam/queue
+ import gleam/int
+ import gleam/list
+ import gleam/should
+ import gleam/pair
- queue.from_list([""])
- |> queue.is_empty
- |> should.be_false
-}
+ pub fn from_and_to_list_test() {
+ queue.from_list([])
+ |> should.equal(queue.new())
-pub fn length_test() {
- let test = fn(input) {
- queue.from_list(input)
- |> queue.length
- |> should.equal(list.length(input))
+ [1, 2, 3]
+ |> queue.from_list
+ |> queue.to_list
+ |> should.equal([1, 2, 3])
}
- test([])
- test([1])
- test([1, 2])
- test([1, 2, 1])
- test([1, 2, 1, 5, 2, 7, 2, 7, 8, 4, 545])
-}
-
-pub fn push_back_test() {
- [1, 2]
- |> queue.from_list
- |> queue.push_back(3)
- |> queue.to_list
- |> should.equal([1, 2, 3])
-
- queue.new()
- |> queue.push_back(1)
- |> queue.push_back(2)
- |> queue.push_back(3)
- |> queue.to_list
- |> should.equal([1, 2, 3])
-}
+ pub fn is_empty_test() {
+ queue.new()
+ |> queue.is_empty
+ |> should.be_true
-pub fn push_front_test() {
- [2, 3]
- |> queue.from_list
- |> queue.push_front(1)
- |> queue.push_front(0)
- |> queue.to_list
- |> should.equal([0, 1, 2, 3])
-}
+ queue.from_list([""])
+ |> queue.is_empty
+ |> should.be_false
+ }
-pub fn push_test() {
- queue.new()
- |> queue.push_front("b")
- |> queue.push_back("x")
- |> queue.push_front("a")
- |> queue.push_back("y")
- |> queue.to_list
- |> should.equal(["a", "b", "x", "y"])
-}
+ pub fn length_test() {
+ let test = fn(input) {
+ queue.from_list(input)
+ |> queue.length
+ |> should.equal(list.length(input))
+ }
+
+ test([])
+ test([1])
+ test([1, 2])
+ test([1, 2, 1])
+ test([1, 2, 1, 5, 2, 7, 2, 7, 8, 4, 545])
+ }
-pub fn pop_back_test() {
- assert Ok(tup) =
- [1, 2, 3]
+ pub fn push_back_test() {
+ [1, 2]
|> queue.from_list
- |> queue.pop_back
-
- tup
- |> pair.first
- |> should.equal(3)
-
- tup
- |> pair.second
- |> queue.is_equal(queue.from_list([1, 2]))
- |> should.be_true
-}
+ |> queue.push_back(3)
+ |> queue.to_list
+ |> should.equal([1, 2, 3])
-pub fn pop_back_after_push_back_test() {
- assert Ok(tup) =
queue.new()
|> queue.push_back(1)
|> queue.push_back(2)
|> queue.push_back(3)
- |> queue.pop_back
+ |> queue.to_list
+ |> should.equal([1, 2, 3])
+ }
- tup
- |> pair.first
- |> should.equal(3)
-}
+ pub fn push_front_test() {
+ [2, 3]
+ |> queue.from_list
+ |> queue.push_front(1)
+ |> queue.push_front(0)
+ |> queue.to_list
+ |> should.equal([0, 1, 2, 3])
+ }
-pub fn pop_back_after_push_test() {
- assert Ok(tup) =
+ pub fn push_test() {
queue.new()
|> queue.push_front("b")
|> queue.push_back("x")
|> queue.push_front("a")
|> queue.push_back("y")
- |> queue.pop_back
+ |> queue.to_list
+ |> should.equal(["a", "b", "x", "y"])
+ }
- tup
- |> pair.first
- |> should.equal("y")
-}
+ pub fn pop_back_test() {
+ assert Ok(tup) =
+ [1, 2, 3]
+ |> queue.from_list
+ |> queue.pop_back
-pub fn pop_back_empty_test() {
- queue.from_list([])
- |> queue.pop_back
- |> should.equal(Error(Nil))
-}
+ tup
+ |> pair.first
+ |> should.equal(3)
-pub fn pop_front_test() {
- assert Ok(tup) =
- [1, 2, 3]
- |> queue.from_list
- |> queue.pop_front
+ tup
+ |> pair.second
+ |> queue.is_equal(queue.from_list([1, 2]))
+ |> should.be_true
+ }
- tup
- |> pair.first
- |> should.equal(1)
+ pub fn pop_back_after_push_back_test() {
+ assert Ok(tup) =
+ queue.new()
+ |> queue.push_back(1)
+ |> queue.push_back(2)
+ |> queue.push_back(3)
+ |> queue.pop_back
+
+ tup
+ |> pair.first
+ |> should.equal(3)
+ }
- tup
- |> pair.second
- |> queue.is_equal(queue.from_list([2, 3]))
- |> should.be_true
-}
+ pub fn pop_back_after_push_test() {
+ assert Ok(tup) =
+ queue.new()
+ |> queue.push_front("b")
+ |> queue.push_back("x")
+ |> queue.push_front("a")
+ |> queue.push_back("y")
+ |> queue.pop_back
+
+ tup
+ |> pair.first
+ |> should.equal("y")
+ }
-pub fn pop_front_after_push_front_test() {
- assert Ok(tup) =
- queue.new()
- |> queue.push_front(3)
- |> queue.push_front(2)
- |> queue.push_front(1)
- |> queue.pop_front
+ pub fn pop_back_empty_test() {
+ queue.from_list([])
+ |> queue.pop_back
+ |> should.equal(Error(Nil))
+ }
- tup
- |> pair.first
- |> should.equal(1)
-}
+ pub fn pop_front_test() {
+ assert Ok(tup) =
+ [1, 2, 3]
+ |> queue.from_list
+ |> queue.pop_front
-pub fn pop_front_after_push_test() {
- assert Ok(tup) =
- queue.new()
- |> queue.push_front("b")
- |> queue.push_back("x")
- |> queue.push_front("a")
- |> queue.pop_front
+ tup
+ |> pair.first
+ |> should.equal(1)
- tup
- |> pair.first
- |> should.equal("a")
-}
-
-pub fn pop_front_empty_test() {
- queue.from_list([])
- |> queue.pop_front
- |> should.equal(Error(Nil))
-}
+ tup
+ |> pair.second
+ |> queue.is_equal(queue.from_list([2, 3]))
+ |> should.be_true
+ }
-pub fn reverse_test() {
- queue.from_list([1, 2, 3])
- |> queue.reverse
- |> queue.to_list
- |> should.equal([3, 2, 1])
-
- queue.new()
- |> queue.push_back(1)
- |> queue.push_back(2)
- |> queue.push_back(3)
- |> queue.reverse
- |> queue.to_list
- |> should.equal([3, 2, 1])
-
- queue.new()
- |> queue.push_front(1)
- |> queue.push_front(2)
- |> queue.push_front(3)
- |> queue.reverse
- |> queue.to_list
- |> should.equal([1, 2, 3])
-
- queue.new()
- |> queue.push_front(1)
- |> queue.push_front(2)
- |> queue.push_back(3)
- |> queue.push_back(4)
- |> queue.reverse
- |> queue.to_list
- |> should.equal([4, 3, 1, 2])
-}
+ pub fn pop_front_after_push_front_test() {
+ assert Ok(tup) =
+ queue.new()
+ |> queue.push_front(3)
+ |> queue.push_front(2)
+ |> queue.push_front(1)
+ |> queue.pop_front
+
+ tup
+ |> pair.first
+ |> should.equal(1)
+ }
-pub fn is_equal_test() {
- let should_equal = fn(a, b) {
- a
- |> queue.is_equal(to: b)
- |> should.be_true
+ pub fn pop_front_after_push_test() {
+ assert Ok(tup) =
+ queue.new()
+ |> queue.push_front("b")
+ |> queue.push_back("x")
+ |> queue.push_front("a")
+ |> queue.pop_front
+
+ tup
+ |> pair.first
+ |> should.equal("a")
}
- let should_not_equal = fn(a, b) {
- a
- |> queue.is_equal(to: b)
- |> should.be_false
+ pub fn pop_front_empty_test() {
+ queue.from_list([])
+ |> queue.pop_front
+ |> should.equal(Error(Nil))
}
- should_equal(queue.new(), queue.new())
+ pub fn reverse_test() {
+ queue.from_list([1, 2, 3])
+ |> queue.reverse
+ |> queue.to_list
+ |> should.equal([3, 2, 1])
- queue.new()
- |> queue.push_front(1)
- |> should_equal(
queue.new()
- |> queue.push_back(1),
- )
+ |> queue.push_back(1)
+ |> queue.push_back(2)
+ |> queue.push_back(3)
+ |> queue.reverse
+ |> queue.to_list
+ |> should.equal([3, 2, 1])
- queue.new()
- |> queue.push_front(1)
- |> should_equal(
queue.new()
- |> queue.push_front(1),
- )
+ |> queue.push_front(1)
+ |> queue.push_front(2)
+ |> queue.push_front(3)
+ |> queue.reverse
+ |> queue.to_list
+ |> should.equal([1, 2, 3])
- queue.new()
- |> queue.push_back(1)
- |> queue.push_back(2)
- |> should_equal(
queue.new()
+ |> queue.push_front(1)
|> queue.push_front(2)
- |> queue.push_front(1),
- )
+ |> queue.push_back(3)
+ |> queue.push_back(4)
+ |> queue.reverse
+ |> queue.to_list
+ |> should.equal([4, 3, 1, 2])
+ }
+
+ pub fn is_equal_test() {
+ let should_equal = fn(a, b) {
+ a
+ |> queue.is_equal(to: b)
+ |> should.be_true
+ }
+
+ let should_not_equal = fn(a, b) {
+ a
+ |> queue.is_equal(to: b)
+ |> should.be_false
+ }
+
+ should_equal(queue.new(), queue.new())
- queue.new()
- |> queue.push_back(1)
- |> should_not_equal(
queue.new()
- |> queue.push_front(2)
- |> queue.push_front(1),
- )
+ |> queue.push_front(1)
+ |> should_equal(
+ queue.new()
+ |> queue.push_back(1),
+ )
- queue.new()
- |> queue.push_back(2)
- |> queue.push_back(1)
- |> should_not_equal(
queue.new()
- |> queue.push_front(2)
- |> queue.push_front(1),
- )
-}
+ |> queue.push_front(1)
+ |> should_equal(
+ queue.new()
+ |> queue.push_front(1),
+ )
-pub fn is_logically_equal_test() {
- let both_even_or_odd = fn(a, b) { int.is_even(a) == int.is_even(b) }
+ queue.new()
+ |> queue.push_back(1)
+ |> queue.push_back(2)
+ |> should_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
- let should_equal = fn(a, b) {
- a
- |> queue.is_logically_equal(to: b, checking: both_even_or_odd)
- |> should.be_true
- }
+ queue.new()
+ |> queue.push_back(1)
+ |> should_not_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
- let should_not_equal = fn(a, b) {
- a
- |> queue.is_logically_equal(to: b, checking: both_even_or_odd)
- |> should.be_false
+ queue.new()
+ |> queue.push_back(2)
+ |> queue.push_back(1)
+ |> should_not_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
}
- should_equal(queue.new(), queue.new())
+ pub fn is_logically_equal_test() {
+ let both_even_or_odd = fn(a, b) { int.is_even(a) == int.is_even(b) }
+
+ let should_equal = fn(a, b) {
+ a
+ |> queue.is_logically_equal(to: b, checking: both_even_or_odd)
+ |> should.be_true
+ }
+
+ let should_not_equal = fn(a, b) {
+ a
+ |> queue.is_logically_equal(to: b, checking: both_even_or_odd)
+ |> should.be_false
+ }
+
+ should_equal(queue.new(), queue.new())
- queue.new()
- |> queue.push_front(3)
- |> should_equal(
queue.new()
- |> queue.push_back(1),
- )
+ |> queue.push_front(3)
+ |> should_equal(
+ queue.new()
+ |> queue.push_back(1),
+ )
- queue.new()
- |> queue.push_front(4)
- |> should_equal(
queue.new()
- |> queue.push_back(2),
- )
+ |> queue.push_front(4)
+ |> should_equal(
+ queue.new()
+ |> queue.push_back(2),
+ )
- queue.new()
- |> queue.push_front(3)
- |> should_equal(
queue.new()
- |> queue.push_front(1),
- )
+ |> queue.push_front(3)
+ |> should_equal(
+ queue.new()
+ |> queue.push_front(1),
+ )
- queue.new()
- |> queue.push_back(3)
- |> queue.push_back(4)
- |> should_equal(
queue.new()
- |> queue.push_front(2)
- |> queue.push_front(1),
- )
+ |> queue.push_back(3)
+ |> queue.push_back(4)
+ |> should_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
- queue.new()
- |> queue.push_back(1)
- |> should_not_equal(
queue.new()
- |> queue.push_front(2)
- |> queue.push_front(1),
- )
+ |> queue.push_back(1)
+ |> should_not_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
- queue.new()
- |> queue.push_back(2)
- |> queue.push_back(1)
- |> should_not_equal(
queue.new()
- |> queue.push_front(2)
- |> queue.push_front(1),
- )
+ |> queue.push_back(2)
+ |> queue.push_back(1)
+ |> should_not_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
- queue.new()
- |> queue.push_back(4)
- |> queue.push_back(3)
- |> should_not_equal(
queue.new()
- |> queue.push_front(2)
- |> queue.push_front(1),
- )
+ |> queue.push_back(4)
+ |> queue.push_back(3)
+ |> should_not_equal(
+ queue.new()
+ |> queue.push_front(2)
+ |> queue.push_front(1),
+ )
+ }
}
diff --git a/test/gleam/regex_test.gleam b/test/gleam/regex_test.gleam
index 1b45c2d..f6410e4 100644
--- a/test/gleam/regex_test.gleam
+++ b/test/gleam/regex_test.gleam
@@ -1,78 +1,84 @@
-import gleam/io
-import gleam/option.{None, Some}
-import gleam/regex.{CompileError, Match, Options}
-import gleam/should
+if erlang {
+ import gleam/io
+ import gleam/option.{None, Some}
+ import gleam/regex.{CompileError, Match, Options}
+ import gleam/should
-pub fn from_string_test() {
- assert Ok(re) = regex.from_string("[0-9]")
+ pub fn from_string_test() {
+ assert Ok(re) = regex.from_string("[0-9]")
- regex.check(re, "abc123")
- |> should.equal(True)
+ regex.check(re, "abc123")
+ |> should.equal(True)
- regex.check(re, "abcxyz")
- |> should.equal(False)
+ regex.check(re, "abcxyz")
+ |> should.equal(False)
- assert Error(from_string_err) = regex.from_string("[0-9")
+ assert Error(from_string_err) = regex.from_string("[0-9")
- from_string_err
- |> should.equal(CompileError(
- error: "missing terminating ] for character class",
- byte_index: 4,
- ))
-}
+ from_string_err
+ |> should.equal(CompileError(
+ error: "missing terminating ] for character class",
+ byte_index: 4,
+ ))
+ }
-pub fn compile_test() {
- let options = Options(case_insensitive: True, multi_line: False)
- assert Ok(re) = regex.compile("[A-B]", options)
+ pub fn compile_test() {
+ let options = Options(case_insensitive: True, multi_line: False)
+ assert Ok(re) = regex.compile("[A-B]", options)
- regex.check(re, "abc123")
- |> should.equal(True)
+ regex.check(re, "abc123")
+ |> should.equal(True)
- let options = Options(case_insensitive: False, multi_line: True)
- assert Ok(re) = regex.compile("^[0-9]", options)
+ let options = Options(case_insensitive: False, multi_line: True)
+ assert Ok(re) = regex.compile("^[0-9]", options)
- regex.check(re, "abc\n123")
- |> should.equal(True)
-}
+ regex.check(re, "abc\n123")
+ |> should.equal(True)
+ }
-pub fn check_test() {
- assert Ok(re) = regex.from_string("^f.o.?")
+ pub fn check_test() {
+ assert Ok(re) = regex.from_string("^f.o.?")
- regex.check(re, "foo")
- |> should.equal(True)
+ regex.check(re, "foo")
+ |> should.equal(True)
- regex.check(re, "boo")
- |> should.equal(False)
-}
+ regex.check(re, "boo")
+ |> should.equal(False)
+ }
-pub fn split_test() {
- assert Ok(re) = regex.from_string(" *, *")
+ pub fn split_test() {
+ assert Ok(re) = regex.from_string(" *, *")
- regex.split(re, "foo,32, 4, 9 ,0")
- |> should.equal(["foo", "32", "4", "9", "0"])
-}
+ regex.split(re, "foo,32, 4, 9 ,0")
+ |> should.equal(["foo", "32", "4", "9", "0"])
+ }
-pub fn scan_test() {
- assert Ok(re) = regex.from_string("Gl\\w+")
+ pub fn scan_test() {
+ assert Ok(re) = regex.from_string("Gl\\w+")
- regex.scan(re, "!Gleam")
- |> should.equal([Match(content: "Gleam", byte_index: 1, submatches: [])])
+ regex.scan(re, "!Gleam")
+ |> should.equal([Match(content: "Gleam", byte_index: 1, submatches: [])])
- regex.scan(re, "हGleam")
- |> should.equal([Match(content: "Gleam", byte_index: 3, submatches: [])])
+ regex.scan(re, "हGleam")
+ |> should.equal([Match(content: "Gleam", byte_index: 3, submatches: [])])
- regex.scan(re, "𐍈Gleam")
- |> should.equal([Match(content: "Gleam", byte_index: 4, submatches: [])])
+ regex.scan(re, "𐍈Gleam")
+ |> should.equal([Match(content: "Gleam", byte_index: 4, submatches: [])])
- assert Ok(re) = regex.from_string("[oi]n a(.?) (\\w+)")
+ assert Ok(re) = regex.from_string("[oi]n a(.?) (\\w+)")
- regex.scan(re, "I am on a boat in a lake.")
- |> should.equal([
- Match(content: "on a boat", byte_index: 5, submatches: [None, Some("boat")]),
- Match(
- content: "in a lake",
- byte_index: 15,
- submatches: [None, Some("lake")],
- ),
- ])
+ regex.scan(re, "I am on a boat in a lake.")
+ |> should.equal([
+ Match(
+ content: "on a boat",
+ byte_index: 5,
+ submatches: [None, Some("boat")],
+ ),
+ Match(
+ content: "in a lake",
+ byte_index: 15,
+ submatches: [None, Some("lake")],
+ ),
+ ])
+ }
}
diff --git a/test/gleam/result_test.gleam b/test/gleam/result_test.gleam
index a2bd6ff..464aa2b 100644
--- a/test/gleam/result_test.gleam
+++ b/test/gleam/result_test.gleam
@@ -1,169 +1,171 @@
-import gleam/should
-import gleam/result
-
-pub fn is_ok_test() {
- result.is_ok(Ok(1))
- |> should.be_true
-
- result.is_ok(Error(1))
- |> should.be_false
-}
-
-pub fn is_error_test() {
- result.is_error(Ok(1))
- |> should.be_false
-
- result.is_error(Error(1))
- |> should.be_true
-}
-
-pub fn map_test() {
- Ok(1)
- |> result.map(fn(x) { x + 1 })
- |> should.equal(Ok(2))
-
- Ok(1)
- |> result.map(fn(_) { "2" })
- |> should.equal(Ok("2"))
-
- Error(1)
- |> result.map(fn(x) { x + 1 })
- |> should.equal(Error(1))
-}
-
-pub fn map_error_test() {
- Ok(1)
- |> result.map_error(fn(x) { x + 1 })
- |> should.equal(Ok(1))
-
- Error(1)
- |> result.map_error(fn(x) { #("ok", x + 1) })
- |> should.equal(Error(#("ok", 2)))
-}
-
-pub fn flatten_test() {
- Ok(Ok(1))
- |> result.flatten
- |> should.equal(Ok(1))
-
- Ok(Error(1))
- |> result.flatten
- |> should.equal(Error(1))
-
- Error(1)
- |> result.flatten
- |> should.equal(Error(1))
-
- Error(Error(1))
- |> result.flatten
- |> should.equal(Error(Error(1)))
-}
-
-pub fn then_test() {
- Error(1)
- |> result.then(fn(x) { Ok(x + 1) })
- |> should.equal(Error(1))
-
- Ok(1)
- |> result.then(fn(x) { Ok(x + 1) })
- |> should.equal(Ok(2))
-
- Ok(1)
- |> result.then(fn(_) { Ok("type change") })
- |> should.equal(Ok("type change"))
-
- Ok(1)
- |> result.then(fn(_) { Error(1) })
- |> should.equal(Error(1))
-}
-
-pub fn unwrap_test() {
- Ok(1)
- |> result.unwrap(50)
- |> should.equal(1)
-
- Error("nope")
- |> result.unwrap(50)
- |> should.equal(50)
-}
-
-pub fn lazy_unwrap_test() {
- Ok(1)
- |> result.lazy_unwrap(fn() { 50 })
- |> should.equal(1)
-
- Error("nope")
- |> result.lazy_unwrap(fn() { 50 })
- |> should.equal(50)
-}
-
-pub fn nil_error_test() {
- Error("error_string")
- |> result.nil_error
- |> should.equal(Error(Nil))
-
- Error(123)
- |> result.nil_error
- |> should.equal(Error(Nil))
-
- Ok(1)
- |> result.nil_error
- |> should.equal(Ok(1))
-}
-
-pub fn or_test() {
- Ok(1)
- |> result.or(Ok(2))
- |> should.equal(Ok(1))
-
- Ok(1)
- |> result.or(Error("Error 2"))
- |> should.equal(Ok(1))
-
- Error("Error 1")
- |> result.or(Ok(2))
- |> should.equal(Ok(2))
-
- Error("Error 1")
- |> result.or(Error("Error 2"))
- |> should.equal(Error("Error 2"))
-}
-
-pub fn lazy_or_test() {
- Ok(1)
- |> result.lazy_or(fn() { Ok(2) })
- |> should.equal(Ok(1))
-
- Ok(1)
- |> result.lazy_or(fn() { Error("Error 2") })
- |> should.equal(Ok(1))
-
- Error("Error 1")
- |> result.lazy_or(fn() { Ok(2) })
- |> should.equal(Ok(2))
-
- Error("Error 1")
- |> result.lazy_or(fn() { Error("Error 2") })
- |> should.equal(Error("Error 2"))
-}
-
-pub fn all_test() {
- [Ok(1), Ok(2), Ok(3)]
- |> result.all
- |> should.equal(Ok([1, 2, 3]))
-
- [Ok(1), Error("a"), Error("b"), Ok(3)]
- |> result.all
- |> should.equal(Error("a"))
-}
-
-pub fn replace_error_test() {
- Error(Nil)
- |> result.replace_error("Invalid")
- |> should.equal(Error("Invalid"))
-}
-
-pub fn values_test() {
- result.values([Ok(1), Error(""), Ok(3)])
- |> should.equal([1, 3])
+if erlang {
+ import gleam/should
+ import gleam/result
+
+ pub fn is_ok_test() {
+ result.is_ok(Ok(1))
+ |> should.be_true
+
+ result.is_ok(Error(1))
+ |> should.be_false
+ }
+
+ pub fn is_error_test() {
+ result.is_error(Ok(1))
+ |> should.be_false
+
+ result.is_error(Error(1))
+ |> should.be_true
+ }
+
+ pub fn map_test() {
+ Ok(1)
+ |> result.map(fn(x) { x + 1 })
+ |> should.equal(Ok(2))
+
+ Ok(1)
+ |> result.map(fn(_) { "2" })
+ |> should.equal(Ok("2"))
+
+ Error(1)
+ |> result.map(fn(x) { x + 1 })
+ |> should.equal(Error(1))
+ }
+
+ pub fn map_error_test() {
+ Ok(1)
+ |> result.map_error(fn(x) { x + 1 })
+ |> should.equal(Ok(1))
+
+ Error(1)
+ |> result.map_error(fn(x) { #("ok", x + 1) })
+ |> should.equal(Error(#("ok", 2)))
+ }
+
+ pub fn flatten_test() {
+ Ok(Ok(1))
+ |> result.flatten
+ |> should.equal(Ok(1))
+
+ Ok(Error(1))
+ |> result.flatten
+ |> should.equal(Error(1))
+
+ Error(1)
+ |> result.flatten
+ |> should.equal(Error(1))
+
+ Error(Error(1))
+ |> result.flatten
+ |> should.equal(Error(Error(1)))
+ }
+
+ pub fn then_test() {
+ Error(1)
+ |> result.then(fn(x) { Ok(x + 1) })
+ |> should.equal(Error(1))
+
+ Ok(1)
+ |> result.then(fn(x) { Ok(x + 1) })
+ |> should.equal(Ok(2))
+
+ Ok(1)
+ |> result.then(fn(_) { Ok("type change") })
+ |> should.equal(Ok("type change"))
+
+ Ok(1)
+ |> result.then(fn(_) { Error(1) })
+ |> should.equal(Error(1))
+ }
+
+ pub fn unwrap_test() {
+ Ok(1)
+ |> result.unwrap(50)
+ |> should.equal(1)
+
+ Error("nope")
+ |> result.unwrap(50)
+ |> should.equal(50)
+ }
+
+ pub fn lazy_unwrap_test() {
+ Ok(1)
+ |> result.lazy_unwrap(fn() { 50 })
+ |> should.equal(1)
+
+ Error("nope")
+ |> result.lazy_unwrap(fn() { 50 })
+ |> should.equal(50)
+ }
+
+ pub fn nil_error_test() {
+ Error("error_string")
+ |> result.nil_error
+ |> should.equal(Error(Nil))
+
+ Error(123)
+ |> result.nil_error
+ |> should.equal(Error(Nil))
+
+ Ok(1)
+ |> result.nil_error
+ |> should.equal(Ok(1))
+ }
+
+ pub fn or_test() {
+ Ok(1)
+ |> result.or(Ok(2))
+ |> should.equal(Ok(1))
+
+ Ok(1)
+ |> result.or(Error("Error 2"))
+ |> should.equal(Ok(1))
+
+ Error("Error 1")
+ |> result.or(Ok(2))
+ |> should.equal(Ok(2))
+
+ Error("Error 1")
+ |> result.or(Error("Error 2"))
+ |> should.equal(Error("Error 2"))
+ }
+
+ pub fn lazy_or_test() {
+ Ok(1)
+ |> result.lazy_or(fn() { Ok(2) })
+ |> should.equal(Ok(1))
+
+ Ok(1)
+ |> result.lazy_or(fn() { Error("Error 2") })
+ |> should.equal(Ok(1))
+
+ Error("Error 1")
+ |> result.lazy_or(fn() { Ok(2) })
+ |> should.equal(Ok(2))
+
+ Error("Error 1")
+ |> result.lazy_or(fn() { Error("Error 2") })
+ |> should.equal(Error("Error 2"))
+ }
+
+ pub fn all_test() {
+ [Ok(1), Ok(2), Ok(3)]
+ |> result.all
+ |> should.equal(Ok([1, 2, 3]))
+
+ [Ok(1), Error("a"), Error("b"), Ok(3)]
+ |> result.all
+ |> should.equal(Error("a"))
+ }
+
+ pub fn replace_error_test() {
+ Error(Nil)
+ |> result.replace_error("Invalid")
+ |> should.equal(Error("Invalid"))
+ }
+
+ pub fn values_test() {
+ result.values([Ok(1), Error(""), Ok(3)])
+ |> should.equal([1, 3])
+ }
}
diff --git a/test/gleam/set_test.gleam b/test/gleam/set_test.gleam
index 871c0b6..593727c 100644
--- a/test/gleam/set_test.gleam
+++ b/test/gleam/set_test.gleam
@@ -1,93 +1,95 @@
-import gleam/should
-import gleam/set
-import gleam/list
-import gleam/int
+if erlang {
+ import gleam/should
+ import gleam/set
+ import gleam/list
+ import gleam/int
-pub fn size_test() {
- set.new()
- |> set.size
- |> should.equal(0)
+ pub fn size_test() {
+ set.new()
+ |> set.size
+ |> should.equal(0)
- set.new()
- |> set.insert(1)
- |> set.insert(2)
- |> set.size
- |> should.equal(2)
+ set.new()
+ |> set.insert(1)
+ |> set.insert(2)
+ |> set.size
+ |> should.equal(2)
- set.new()
- |> set.insert(1)
- |> set.insert(1)
- |> set.insert(2)
- |> set.size
- |> should.equal(2)
-}
+ set.new()
+ |> set.insert(1)
+ |> set.insert(1)
+ |> set.insert(2)
+ |> set.size
+ |> should.equal(2)
+ }
-pub fn contains_test() {
- set.new()
- |> set.insert(1)
- |> set.contains(this: 1)
- |> should.be_true
+ pub fn contains_test() {
+ set.new()
+ |> set.insert(1)
+ |> set.contains(this: 1)
+ |> should.be_true
- set.new()
- |> set.contains(this: 1)
- |> should.be_false
-}
+ set.new()
+ |> set.contains(this: 1)
+ |> should.be_false
+ }
-pub fn delete_test() {
- set.new()
- |> set.insert(1)
- |> set.delete(1)
- |> set.contains(1)
- |> should.be_false
-}
+ pub fn delete_test() {
+ set.new()
+ |> set.insert(1)
+ |> set.delete(1)
+ |> set.contains(1)
+ |> should.be_false
+ }
-pub fn to_list_test() {
- set.new()
- |> set.insert(2)
- |> set.insert(3)
- |> set.insert(4)
- |> set.to_list
- |> list.sort(by: int.compare)
- |> should.equal([2, 3, 4])
-}
+ pub fn to_list_test() {
+ set.new()
+ |> set.insert(2)
+ |> set.insert(3)
+ |> set.insert(4)
+ |> set.to_list
+ |> list.sort(by: int.compare)
+ |> should.equal([2, 3, 4])
+ }
-pub fn from_list_test() {
- [1, 1, 2, 4, 3, 2]
- |> set.from_list
- |> set.to_list
- |> list.sort(by: int.compare)
- |> should.equal([1, 2, 3, 4])
-}
+ pub fn from_list_test() {
+ [1, 1, 2, 4, 3, 2]
+ |> set.from_list
+ |> set.to_list
+ |> list.sort(by: int.compare)
+ |> should.equal([1, 2, 3, 4])
+ }
-pub fn fold_test() {
- [1, 3, 9]
- |> set.from_list
- |> set.fold(from: 0, with: fn(m, a) { m + a })
-}
+ pub fn fold_test() {
+ [1, 3, 9]
+ |> set.from_list
+ |> set.fold(from: 0, with: fn(m, a) { m + a })
+ }
-pub fn filter_test() {
- [1, 4, 6, 3, 675, 44, 67]
- |> set.from_list()
- |> set.filter(for: int.is_even)
- |> set.to_list
- |> should.equal([4, 6, 44])
-}
+ pub fn filter_test() {
+ [1, 4, 6, 3, 675, 44, 67]
+ |> set.from_list()
+ |> set.filter(for: int.is_even)
+ |> set.to_list
+ |> should.equal([4, 6, 44])
+ }
-pub fn take_test() {
- [1, 2, 3]
- |> set.from_list
- |> set.take([1, 3, 5])
- |> should.equal(set.from_list([1, 3]))
-}
+ pub fn take_test() {
+ [1, 2, 3]
+ |> set.from_list
+ |> set.take([1, 3, 5])
+ |> should.equal(set.from_list([1, 3]))
+ }
-pub fn union_test() {
- set.union(set.from_list([1, 2]), set.from_list([2, 3]))
- |> set.to_list
- |> should.equal([1, 2, 3])
-}
+ pub fn union_test() {
+ set.union(set.from_list([1, 2]), set.from_list([2, 3]))
+ |> set.to_list
+ |> should.equal([1, 2, 3])
+ }
-pub fn intersection_test() {
- set.intersection(set.from_list([1, 2]), set.from_list([2, 3]))
- |> set.to_list
- |> should.equal([2])
+ pub fn intersection_test() {
+ set.intersection(set.from_list([1, 2]), set.from_list([2, 3]))
+ |> set.to_list
+ |> should.equal([2])
+ }
}
diff --git a/test/gleam/string_builder_test.gleam b/test/gleam/string_builder_test.gleam
index fdbd048..663d3b9 100644
--- a/test/gleam/string_builder_test.gleam
+++ b/test/gleam/string_builder_test.gleam
@@ -1,102 +1,104 @@
-import gleam/should
-import gleam/string_builder
-
-pub fn string_builder_test() {
- let data =
- string_builder.from_string("ello")
- |> string_builder.append(",")
- |> string_builder.append(" world!")
- |> string_builder.prepend("H")
-
- data
- |> string_builder.to_string
- |> should.equal("Hello, world!")
-
- data
- |> string_builder.byte_size
- |> should.equal(13)
-
- let data =
- string_builder.from_string("ello")
- |> string_builder.append_builder(string_builder.from_string(","))
- |> string_builder.append_builder(string_builder.concat([
- string_builder.from_string(" wo"),
- string_builder.from_string("rld!"),
- ]))
- |> string_builder.prepend_builder(string_builder.from_string("H"))
-
- data
- |> string_builder.to_string
- |> should.equal("Hello, world!")
-
- data
- |> string_builder.byte_size
- |> should.equal(13)
-}
-
-pub fn lowercase_test() {
- ["Gleam", "Gleam"]
- |> string_builder.from_strings
- |> string_builder.lowercase
- |> string_builder.to_string
- |> should.equal("gleamgleam")
-}
-
-pub fn uppercase_test() {
- ["Gleam", "Gleam"]
- |> string_builder.from_strings
- |> string_builder.uppercase
- |> string_builder.to_string
- |> should.equal("GLEAMGLEAM")
-}
-
-pub fn split_test() {
- "Gleam,Erlang,Elixir"
- |> string_builder.from_string
- |> string_builder.split(",")
- |> should.equal([
- string_builder.from_string("Gleam"),
- string_builder.from_string("Erlang"),
- string_builder.from_string("Elixir"),
- ])
-
- ["Gleam, Erl", "ang,Elixir"]
- |> string_builder.from_strings
- |> string_builder.split(", ")
- |> should.equal([
- string_builder.from_string("Gleam"),
- string_builder.from_strings(["Erl", "ang,Elixir"]),
- ])
-}
-
-pub fn is_equal_test() {
- string_builder.from_string("12")
- |> string_builder.is_equal(string_builder.from_strings(["1", "2"]))
- |> should.be_true
-
- string_builder.from_string("12")
- |> string_builder.is_equal(string_builder.from_string("12"))
- |> should.be_true
-
- string_builder.from_string("12")
- |> string_builder.is_equal(string_builder.from_string("2"))
- |> should.be_false
-}
-
-pub fn is_empty_test() {
- string_builder.from_string("")
- |> string_builder.is_empty
- |> should.be_true
-
- string_builder.from_string("12")
- |> string_builder.is_empty
- |> should.be_false
-
- string_builder.from_strings([])
- |> string_builder.is_empty
- |> should.be_true
-
- string_builder.from_strings(["", ""])
- |> string_builder.is_empty
- |> should.be_true
+if erlang {
+ import gleam/should
+ import gleam/string_builder
+
+ pub fn string_builder_test() {
+ let data =
+ string_builder.from_string("ello")
+ |> string_builder.append(",")
+ |> string_builder.append(" world!")
+ |> string_builder.prepend("H")
+
+ data
+ |> string_builder.to_string
+ |> should.equal("Hello, world!")
+
+ data
+ |> string_builder.byte_size
+ |> should.equal(13)
+
+ let data =
+ string_builder.from_string("ello")
+ |> string_builder.append_builder(string_builder.from_string(","))
+ |> string_builder.append_builder(string_builder.concat([
+ string_builder.from_string(" wo"),
+ string_builder.from_string("rld!"),
+ ]))
+ |> string_builder.prepend_builder(string_builder.from_string("H"))
+
+ data
+ |> string_builder.to_string
+ |> should.equal("Hello, world!")
+
+ data
+ |> string_builder.byte_size
+ |> should.equal(13)
+ }
+
+ pub fn lowercase_test() {
+ ["Gleam", "Gleam"]
+ |> string_builder.from_strings
+ |> string_builder.lowercase
+ |> string_builder.to_string
+ |> should.equal("gleamgleam")
+ }
+
+ pub fn uppercase_test() {
+ ["Gleam", "Gleam"]
+ |> string_builder.from_strings
+ |> string_builder.uppercase
+ |> string_builder.to_string
+ |> should.equal("GLEAMGLEAM")
+ }
+
+ pub fn split_test() {
+ "Gleam,Erlang,Elixir"
+ |> string_builder.from_string
+ |> string_builder.split(",")
+ |> should.equal([
+ string_builder.from_string("Gleam"),
+ string_builder.from_string("Erlang"),
+ string_builder.from_string("Elixir"),
+ ])
+
+ ["Gleam, Erl", "ang,Elixir"]
+ |> string_builder.from_strings
+ |> string_builder.split(", ")
+ |> should.equal([
+ string_builder.from_string("Gleam"),
+ string_builder.from_strings(["Erl", "ang,Elixir"]),
+ ])
+ }
+
+ pub fn is_equal_test() {
+ string_builder.from_string("12")
+ |> string_builder.is_equal(string_builder.from_strings(["1", "2"]))
+ |> should.be_true
+
+ string_builder.from_string("12")
+ |> string_builder.is_equal(string_builder.from_string("12"))
+ |> should.be_true
+
+ string_builder.from_string("12")
+ |> string_builder.is_equal(string_builder.from_string("2"))
+ |> should.be_false
+ }
+
+ pub fn is_empty_test() {
+ string_builder.from_string("")
+ |> string_builder.is_empty
+ |> should.be_true
+
+ string_builder.from_string("12")
+ |> string_builder.is_empty
+ |> should.be_false
+
+ string_builder.from_strings([])
+ |> string_builder.is_empty
+ |> should.be_true
+
+ string_builder.from_strings(["", ""])
+ |> string_builder.is_empty
+ |> should.be_true
+ }
}
diff --git a/test/gleam/string_test.gleam b/test/gleam/string_test.gleam
index 805f3ae..085e2f9 100644
--- a/test/gleam/string_test.gleam
+++ b/test/gleam/string_test.gleam
@@ -1,332 +1,334 @@
-import gleam/string
-import gleam/should
-import gleam/order
-
-pub fn length_test() {
- string.length("ß↑e̊")
- |> should.equal(3)
-
- string.length("Gleam")
- |> should.equal(5)
-
- string.length("")
- |> should.equal(0)
-}
-
-pub fn lowercase_test() {
- string.lowercase("Gleam")
- |> should.equal("gleam")
-}
-
-pub fn uppercase_test() {
- string.uppercase("Gleam")
- |> should.equal("GLEAM")
-}
-
-pub fn reverse_test() {
- string.reverse("Gleam")
- |> should.equal("maelG")
-}
-
-pub fn split_test() {
- "Gleam,Erlang,Elixir"
- |> string.split(",")
- |> should.equal(["Gleam", "Erlang", "Elixir"])
-
- "Gleam, Erlang,Elixir"
- |> string.split(", ")
- |> should.equal(["Gleam", "Erlang,Elixir"])
-}
-
-pub fn split_once_test() {
- "Gleam,Erlang,Elixir"
- |> string.split_once(",")
- |> should.equal(Ok(#("Gleam", "Erlang,Elixir")))
-
- "Gleam"
- |> string.split_once(",")
- |> should.equal(Error(Nil))
-
- ""
- |> string.split_once(",")
- |> should.equal(Error(Nil))
-}
-
-pub fn replace_test() {
- "Gleam,Erlang,Elixir"
- |> string.replace(",", "++")
- |> should.equal("Gleam++Erlang++Elixir")
-}
-
-pub fn append_test() {
- "Test"
- |> string.append(" Me")
- |> should.equal("Test Me")
-}
-
-pub fn compare_test() {
- string.compare("", "")
- |> should.equal(order.Eq)
-
- string.compare("a", "")
- |> should.equal(order.Gt)
-
- string.compare("a", "A")
- |> should.equal(order.Gt)
-
- string.compare("A", "B")
- |> should.equal(order.Lt)
-
- string.compare("t", "ABC")
- |> should.equal(order.Gt)
-}
-
-pub fn contains_test() {
- "gleam"
- |> string.contains("ea")
- |> should.equal(True)
-
- "gleam"
- |> string.contains("x")
- |> should.equal(False)
-
- string.contains(does: "bellwether", contain: "bell")
- |> should.equal(True)
-}
-
-pub fn concat_test() {
- ["Hello", ", ", "world!"]
- |> string.concat
- |> should.equal("Hello, world!")
-}
-
-pub fn repeat_test() {
- "hi"
- |> string.repeat(times: 3)
- |> should.equal("hihihi")
-
- "hi"
- |> string.repeat(0)
- |> should.equal("")
-
- "hi"
- |> string.repeat(-1)
- |> should.equal("")
-}
-
-pub fn join_test() {
- ["Hello", "world!"]
- |> string.join(with: ", ")
- |> should.equal("Hello, world!")
-
- ["Hello", "world!"]
- |> string.join(with: "-")
- |> should.equal("Hello-world!")
-}
-
-pub fn trim_test() {
- " hats \n"
- |> string.trim()
- |> should.equal("hats")
-}
-
-pub fn trim_left_test() {
- " hats \n"
- |> string.trim_left()
- |> should.equal("hats \n")
-}
-
-pub fn trim_right_test() {
- " hats \n"
- |> string.trim_right()
- |> should.equal(" hats")
-}
-
-pub fn starts_with_test() {
- "theory"
- |> string.starts_with("")
- |> should.equal(True)
-
- "theory"
- |> string.starts_with("the")
- |> should.equal(True)
-
- "theory"
- |> string.starts_with("ory")
- |> should.equal(False)
-
- "theory"
- |> string.starts_with("theory2")
- |> should.equal(False)
-}
-
-pub fn ends_with_test() {
- "theory"
- |> string.ends_with("")
- |> should.equal(True)
-
- "theory"
- |> string.ends_with("ory")
- |> should.equal(True)
-
- "theory"
- |> string.ends_with("the")
- |> should.equal(False)
-
- "theory"
- |> string.ends_with("theory2")
- |> should.equal(False)
-}
-
-pub fn slice_test() {
- "gleam"
- |> string.slice(at_index: 1, length: 2)
- |> should.equal("le")
-
- "gleam"
- |> string.slice(at_index: 1, length: 10)
- |> should.equal("leam")
-
- "gleam"
- |> string.slice(at_index: 10, length: 3)
- |> should.equal("")
-
- "gleam"
- |> string.slice(at_index: -2, length: 2)
- |> should.equal("am")
-
- "gleam"
- |> string.slice(at_index: -12, length: 2)
- |> should.equal("")
-
- "gleam"
- |> string.slice(at_index: 2, length: -3)
- |> should.equal("")
-}
-
-pub fn crop_test() {
- "gleam"
- |> string.crop("gl")
- |> should.equal("gleam")
-
- "gleam"
- |> string.crop("le")
- |> should.equal("leam")
-
- string.crop(from: "gleam", before: "ea")
- |> should.equal("eam")
-
- "gleam"
- |> string.crop("")
- |> should.equal("gleam")
-
- "gleam"
- |> string.crop("!")
- |> should.equal("gleam")
-}
-
-pub fn drop_left_test() {
- "gleam"
- |> string.drop_left(up_to: 2)
- |> should.equal("eam")
-
- "gleam"
- |> string.drop_left(up_to: 6)
- |> should.equal("")
-
- "gleam"
- |> string.drop_left(up_to: -2)
- |> should.equal("gleam")
-}
-
-pub fn drop_right_test() {
- "gleam"
- |> string.drop_right(up_to: 2)
- |> should.equal("gle")
-
- "gleam"
- |> string.drop_right(up_to: 5)
- |> should.equal("")
-
- "gleam"
- |> string.drop_right(up_to: -2)
- |> should.equal("gleam")
-}
-
-pub fn pad_left_test() {
- "121"
- |> string.pad_left(to: 5, with: ".")
- |> should.equal("..121")
-
- "121"
- |> string.pad_left(to: 3, with: ".")
- |> should.equal("121")
-
- "121"
- |> string.pad_left(to: 2, with: ".")
- |> should.equal("121")
-
- "121"
- |> string.pad_left(to: 5, with: "XY")
- |> should.equal("XYXY121")
-}
-
-pub fn pad_right_test() {
- "121"
- |> string.pad_right(to: 5, with: ".")
- |> should.equal("121..")
-
- "121"
- |> string.pad_right(to: 3, with: ".")
- |> should.equal("121")
-
- "121"
- |> string.pad_right(to: 2, with: ".")
- |> should.equal("121")
-
- "121"
- |> string.pad_right(to: 5, with: "XY")
- |> should.equal("121XYXY")
-}
-
-pub fn pop_grapheme_test() {
- "gleam"
- |> string.pop_grapheme()
- |> should.equal(Ok(#("g", "leam")))
-
- "g"
- |> string.pop_grapheme()
- |> should.equal(Ok(#("g", "")))
-
- ""
- |> string.pop_grapheme()
- |> should.equal(Error(Nil))
-}
-
-pub fn to_graphemes_test() {
- "abc"
- |> string.to_graphemes()
- |> should.equal(["a", "b", "c"])
-
- "a"
- |> string.to_graphemes()
- |> should.equal(["a"])
-
- ""
- |> string.to_graphemes()
- |> should.equal([])
-}
-
-pub fn utf_codepoint_test() {
- string.utf_codepoint(1114444)
- |> should.be_error
-
- string.utf_codepoint(65534)
- |> should.be_error
-
- string.utf_codepoint(55296)
- |> should.be_error
-
- assert Ok(snake) = string.utf_codepoint(128013)
- should.equal(<<snake:utf8_codepoint>>, <<"🐍":utf8>>)
+if erlang {
+ import gleam/string
+ import gleam/should
+ import gleam/order
+
+ pub fn length_test() {
+ string.length("ß↑e̊")
+ |> should.equal(3)
+
+ string.length("Gleam")
+ |> should.equal(5)
+
+ string.length("")
+ |> should.equal(0)
+ }
+
+ pub fn lowercase_test() {
+ string.lowercase("Gleam")
+ |> should.equal("gleam")
+ }
+
+ pub fn uppercase_test() {
+ string.uppercase("Gleam")
+ |> should.equal("GLEAM")
+ }
+
+ pub fn reverse_test() {
+ string.reverse("Gleam")
+ |> should.equal("maelG")
+ }
+
+ pub fn split_test() {
+ "Gleam,Erlang,Elixir"
+ |> string.split(",")
+ |> should.equal(["Gleam", "Erlang", "Elixir"])
+
+ "Gleam, Erlang,Elixir"
+ |> string.split(", ")
+ |> should.equal(["Gleam", "Erlang,Elixir"])
+ }
+
+ pub fn split_once_test() {
+ "Gleam,Erlang,Elixir"
+ |> string.split_once(",")
+ |> should.equal(Ok(#("Gleam", "Erlang,Elixir")))
+
+ "Gleam"
+ |> string.split_once(",")
+ |> should.equal(Error(Nil))
+
+ ""
+ |> string.split_once(",")
+ |> should.equal(Error(Nil))
+ }
+
+ pub fn replace_test() {
+ "Gleam,Erlang,Elixir"
+ |> string.replace(",", "++")
+ |> should.equal("Gleam++Erlang++Elixir")
+ }
+
+ pub fn append_test() {
+ "Test"
+ |> string.append(" Me")
+ |> should.equal("Test Me")
+ }
+
+ pub fn compare_test() {
+ string.compare("", "")
+ |> should.equal(order.Eq)
+
+ string.compare("a", "")
+ |> should.equal(order.Gt)
+
+ string.compare("a", "A")
+ |> should.equal(order.Gt)
+
+ string.compare("A", "B")
+ |> should.equal(order.Lt)
+
+ string.compare("t", "ABC")
+ |> should.equal(order.Gt)
+ }
+
+ pub fn contains_test() {
+ "gleam"
+ |> string.contains("ea")
+ |> should.equal(True)
+
+ "gleam"
+ |> string.contains("x")
+ |> should.equal(False)
+
+ string.contains(does: "bellwether", contain: "bell")
+ |> should.equal(True)
+ }
+
+ pub fn concat_test() {
+ ["Hello", ", ", "world!"]
+ |> string.concat
+ |> should.equal("Hello, world!")
+ }
+
+ pub fn repeat_test() {
+ "hi"
+ |> string.repeat(times: 3)
+ |> should.equal("hihihi")
+
+ "hi"
+ |> string.repeat(0)
+ |> should.equal("")
+
+ "hi"
+ |> string.repeat(-1)
+ |> should.equal("")
+ }
+
+ pub fn join_test() {
+ ["Hello", "world!"]
+ |> string.join(with: ", ")
+ |> should.equal("Hello, world!")
+
+ ["Hello", "world!"]
+ |> string.join(with: "-")
+ |> should.equal("Hello-world!")
+ }
+
+ pub fn trim_test() {
+ " hats \n"
+ |> string.trim()
+ |> should.equal("hats")
+ }
+
+ pub fn trim_left_test() {
+ " hats \n"
+ |> string.trim_left()
+ |> should.equal("hats \n")
+ }
+
+ pub fn trim_right_test() {
+ " hats \n"
+ |> string.trim_right()
+ |> should.equal(" hats")
+ }
+
+ pub fn starts_with_test() {
+ "theory"
+ |> string.starts_with("")
+ |> should.equal(True)
+
+ "theory"
+ |> string.starts_with("the")
+ |> should.equal(True)
+
+ "theory"
+ |> string.starts_with("ory")
+ |> should.equal(False)
+
+ "theory"
+ |> string.starts_with("theory2")
+ |> should.equal(False)
+ }
+
+ pub fn ends_with_test() {
+ "theory"
+ |> string.ends_with("")
+ |> should.equal(True)
+
+ "theory"
+ |> string.ends_with("ory")
+ |> should.equal(True)
+
+ "theory"
+ |> string.ends_with("the")
+ |> should.equal(False)
+
+ "theory"
+ |> string.ends_with("theory2")
+ |> should.equal(False)
+ }
+
+ pub fn slice_test() {
+ "gleam"
+ |> string.slice(at_index: 1, length: 2)
+ |> should.equal("le")
+
+ "gleam"
+ |> string.slice(at_index: 1, length: 10)
+ |> should.equal("leam")
+
+ "gleam"
+ |> string.slice(at_index: 10, length: 3)
+ |> should.equal("")
+
+ "gleam"
+ |> string.slice(at_index: -2, length: 2)
+ |> should.equal("am")
+
+ "gleam"
+ |> string.slice(at_index: -12, length: 2)
+ |> should.equal("")
+
+ "gleam"
+ |> string.slice(at_index: 2, length: -3)
+ |> should.equal("")
+ }
+
+ pub fn crop_test() {
+ "gleam"
+ |> string.crop("gl")
+ |> should.equal("gleam")
+
+ "gleam"
+ |> string.crop("le")
+ |> should.equal("leam")
+
+ string.crop(from: "gleam", before: "ea")
+ |> should.equal("eam")
+
+ "gleam"
+ |> string.crop("")
+ |> should.equal("gleam")
+
+ "gleam"
+ |> string.crop("!")
+ |> should.equal("gleam")
+ }
+
+ pub fn drop_left_test() {
+ "gleam"
+ |> string.drop_left(up_to: 2)
+ |> should.equal("eam")
+
+ "gleam"
+ |> string.drop_left(up_to: 6)
+ |> should.equal("")
+
+ "gleam"
+ |> string.drop_left(up_to: -2)
+ |> should.equal("gleam")
+ }
+
+ pub fn drop_right_test() {
+ "gleam"
+ |> string.drop_right(up_to: 2)
+ |> should.equal("gle")
+
+ "gleam"
+ |> string.drop_right(up_to: 5)
+ |> should.equal("")
+
+ "gleam"
+ |> string.drop_right(up_to: -2)
+ |> should.equal("gleam")
+ }
+
+ pub fn pad_left_test() {
+ "121"
+ |> string.pad_left(to: 5, with: ".")
+ |> should.equal("..121")
+
+ "121"
+ |> string.pad_left(to: 3, with: ".")
+ |> should.equal("121")
+
+ "121"
+ |> string.pad_left(to: 2, with: ".")
+ |> should.equal("121")
+
+ "121"
+ |> string.pad_left(to: 5, with: "XY")
+ |> should.equal("XYXY121")
+ }
+
+ pub fn pad_right_test() {
+ "121"
+ |> string.pad_right(to: 5, with: ".")
+ |> should.equal("121..")
+
+ "121"
+ |> string.pad_right(to: 3, with: ".")
+ |> should.equal("121")
+
+ "121"
+ |> string.pad_right(to: 2, with: ".")
+ |> should.equal("121")
+
+ "121"
+ |> string.pad_right(to: 5, with: "XY")
+ |> should.equal("121XYXY")
+ }
+
+ pub fn pop_grapheme_test() {
+ "gleam"
+ |> string.pop_grapheme()
+ |> should.equal(Ok(#("g", "leam")))
+
+ "g"
+ |> string.pop_grapheme()
+ |> should.equal(Ok(#("g", "")))
+
+ ""
+ |> string.pop_grapheme()
+ |> should.equal(Error(Nil))
+ }
+
+ pub fn to_graphemes_test() {
+ "abc"
+ |> string.to_graphemes()
+ |> should.equal(["a", "b", "c"])
+
+ "a"
+ |> string.to_graphemes()
+ |> should.equal(["a"])
+
+ ""
+ |> string.to_graphemes()
+ |> should.equal([])
+ }
+
+ pub fn utf_codepoint_test() {
+ string.utf_codepoint(1114444)
+ |> should.be_error
+
+ string.utf_codepoint(65534)
+ |> should.be_error
+
+ string.utf_codepoint(55296)
+ |> should.be_error
+
+ assert Ok(snake) = string.utf_codepoint(128013)
+ should.equal(<<snake:utf8_codepoint>>, <<"🐍":utf8>>)
+ }
}
diff --git a/test/gleam/uri_test.gleam b/test/gleam/uri_test.gleam
index c0ee595..9c6d2e0 100644
--- a/test/gleam/uri_test.gleam
+++ b/test/gleam/uri_test.gleam
@@ -1,294 +1,296 @@
-import gleam/uri
-import gleam/should
-import gleam/string
-import gleam/list
-import gleam/option.{None, Some}
-
-pub fn full_parse_test() {
- assert Ok(parsed) =
- uri.parse("https://foo:bar@example.com:1234/path?query=true#fragment")
- should.equal(parsed.scheme, Some("https"))
- should.equal(parsed.userinfo, Some("foo:bar"))
- should.equal(parsed.host, Some("example.com"))
- should.equal(parsed.port, Some(1234))
- should.equal(parsed.path, "/path")
- should.equal(parsed.query, Some("query=true"))
- should.equal(parsed.fragment, Some("fragment"))
-}
-
-pub fn parse_only_path_test() {
- assert Ok(parsed) = uri.parse("")
- should.equal(parsed.scheme, None)
- should.equal(parsed.userinfo, None)
- should.equal(parsed.host, None)
- should.equal(parsed.port, None)
- should.equal(parsed.path, "")
- should.equal(parsed.query, None)
- should.equal(parsed.fragment, None)
-}
-
-pub fn parse_only_host_test() {
- assert Ok(parsed) = uri.parse("//")
- should.equal(parsed.scheme, None)
- should.equal(parsed.userinfo, None)
- should.equal(parsed.host, Some(""))
- should.equal(parsed.port, None)
- should.equal(parsed.path, "")
- should.equal(parsed.query, None)
- should.equal(parsed.fragment, None)
-}
-
-pub fn error_parsing_uri_test() {
- should.equal(uri.parse("::"), Error(Nil))
-}
-
-pub fn full_uri_to_string_test() {
- let test_uri =
- uri.Uri(
- Some("https"),
- Some("foo:bar"),
- Some("example.com"),
- Some(1234),
- "/path",
- Some("query=true"),
- Some("fragment"),
+if erlang {
+ import gleam/uri
+ import gleam/should
+ import gleam/string
+ import gleam/list
+ import gleam/option.{None, Some}
+
+ pub fn full_parse_test() {
+ assert Ok(parsed) =
+ uri.parse("https://foo:bar@example.com:1234/path?query=true#fragment")
+ should.equal(parsed.scheme, Some("https"))
+ should.equal(parsed.userinfo, Some("foo:bar"))
+ should.equal(parsed.host, Some("example.com"))
+ should.equal(parsed.port, Some(1234))
+ should.equal(parsed.path, "/path")
+ should.equal(parsed.query, Some("query=true"))
+ should.equal(parsed.fragment, Some("fragment"))
+ }
+
+ pub fn parse_only_path_test() {
+ assert Ok(parsed) = uri.parse("")
+ should.equal(parsed.scheme, None)
+ should.equal(parsed.userinfo, None)
+ should.equal(parsed.host, None)
+ should.equal(parsed.port, None)
+ should.equal(parsed.path, "")
+ should.equal(parsed.query, None)
+ should.equal(parsed.fragment, None)
+ }
+
+ pub fn parse_only_host_test() {
+ assert Ok(parsed) = uri.parse("//")
+ should.equal(parsed.scheme, None)
+ should.equal(parsed.userinfo, None)
+ should.equal(parsed.host, Some(""))
+ should.equal(parsed.port, None)
+ should.equal(parsed.path, "")
+ should.equal(parsed.query, None)
+ should.equal(parsed.fragment, None)
+ }
+
+ pub fn error_parsing_uri_test() {
+ should.equal(uri.parse("::"), Error(Nil))
+ }
+
+ pub fn full_uri_to_string_test() {
+ let test_uri =
+ uri.Uri(
+ Some("https"),
+ Some("foo:bar"),
+ Some("example.com"),
+ Some(1234),
+ "/path",
+ Some("query=true"),
+ Some("fragment"),
+ )
+ should.equal(
+ uri.to_string(test_uri),
+ "https://foo:bar@example.com:1234/path?query=true#fragment",
)
- should.equal(
- uri.to_string(test_uri),
- "https://foo:bar@example.com:1234/path?query=true#fragment",
- )
-}
-
-pub fn path_only_uri_to_string_test() {
- let test_uri = uri.Uri(None, None, None, None, "/", None, None)
- should.equal(uri.to_string(test_uri), "/")
-}
-
-pub fn parse_query_string_test() {
- assert Ok(parsed) = uri.parse_query("foo+bar=1&city=%C3%B6rebro")
- should.equal(parsed, [#("foo bar", "1"), #("city", "örebro")])
-
- // Duplicates keys not overridden
- assert Ok(parsed) = uri.parse_query("a[]=1&a[]=2")
-
- parsed
- |> should.equal([#("a[]", "1"), #("a[]", "2")])
-}
-
-pub fn parse_empty_query_string_test() {
- assert Ok(parsed) = uri.parse_query("")
- should.equal(parsed, [])
-}
-
-pub fn parse_query_string_with_empty_test() {
- uri.parse_query("present")
- |> should.equal(Ok([#("present", "")]))
-}
-
-pub fn error_parsing_query_test() {
- should.equal(uri.parse_query("%C2"), Error(Nil))
-}
-
-pub fn query_to_string_test() {
- let query_string =
- uri.query_to_string([#("foo bar", "1"), #("city", "örebro")])
- should.equal(query_string, "foo+bar=1&city=%C3%B6rebro")
-}
-
-pub fn empty_query_to_string_test() {
- let query_string = uri.query_to_string([])
- should.equal(query_string, "")
-}
-
-fn percent_codec_fixtures() {
- [
- #(" ", "+"),
- #(",", "%2C"),
- #(";", "%3B"),
- #(":", "%3A"),
- #("!", "%21"),
- #("?", "%3F"),
- #("'", "%27"),
- #("(", "%28"),
- #(")", "%29"),
- #("[", "%5B"),
- #("@", "%40"),
- #("/", "%2F"),
- #("\\", "%5C"),
- #("&", "%26"),
- #("#", "%23"),
- #("=", "%3D"),
- #("~", "%7E"),
- #("ñ", "%C3%B1"),
- // Allowed chars
- #("-", "-"),
- #("_", "_"),
- #(".", "."),
- #("*", "*"),
- #("100% great", "100%25+great"),
- ]
-}
-
-pub fn percent_encode_test() {
- percent_codec_fixtures()
- |> list.map(fn(t) {
- let #(a, b) = t
- uri.percent_encode(a)
- |> should.equal(b)
- })
-}
-
-pub fn percent_encode_consistency_test() {
- let k = "foo bar[]"
- let v = "ñaña (,:*~)"
-
- let query_string = uri.query_to_string([#(k, v)])
-
- let encoded_key = uri.percent_encode(k)
- let encoded_value = uri.percent_encode(v)
- let manual_query_string = string.concat([encoded_key, "=", encoded_value])
-
- should.equal(query_string, manual_query_string)
-}
-
-pub fn percent_decode_test() {
- percent_codec_fixtures()
- |> list.map(fn(t) {
- let #(a, b) = t
- uri.percent_decode(b)
- |> should.equal(Ok(a))
- })
-}
-
-pub fn percent_decode_consistency_test() {
- let k = "foo+bar[]"
- let v = "%C3%B6rebro"
- let query = string.concat([k, "=", v])
- assert Ok(parsed) = uri.parse_query(query)
-
- assert Ok(decoded_key) = uri.percent_decode(k)
- assert Ok(decoded_value) = uri.percent_decode(v)
-
- should.equal(parsed, [#(decoded_key, decoded_value)])
-}
-
-pub fn parse_segments_test() {
- should.equal(uri.path_segments("/"), [])
- should.equal(uri.path_segments("/foo/bar"), ["foo", "bar"])
- should.equal(uri.path_segments("////"), [])
- should.equal(uri.path_segments("/foo//bar"), ["foo", "bar"])
-
- should.equal(uri.path_segments("/."), [])
- should.equal(uri.path_segments("/.foo"), [".foo"])
-
- should.equal(uri.path_segments("/../bar"), ["bar"])
- should.equal(uri.path_segments("../bar"), ["bar"])
- should.equal(uri.path_segments("/foo/../bar"), ["bar"])
-}
-
-pub fn origin_test() {
- assert Ok(parsed) = uri.parse("http://example.test/path?foo#bar")
- uri.origin(parsed)
- |> should.equal(Ok("http://example.test"))
-
- assert Ok(parsed) = uri.parse("http://example.test:8080")
- uri.origin(parsed)
- |> should.equal(Ok("http://example.test:8080"))
-
- assert Ok(parsed) = uri.parse("https://example.test")
- uri.origin(parsed)
- |> should.equal(Ok("https://example.test"))
-
- assert Ok(parsed) = uri.parse("http:///path")
- uri.origin(parsed)
- |> should.equal(Ok("http://"))
-
- assert Ok(parsed) = uri.parse("http://")
- uri.origin(parsed)
- |> should.equal(Ok("http://"))
-
- assert Ok(parsed) = uri.parse("/path")
- uri.origin(parsed)
- |> should.equal(Error(Nil))
-
- assert Ok(parsed) = uri.parse("file:///dev/null")
- uri.origin(parsed)
- |> should.equal(Error(Nil))
-}
-
-pub fn merge_test() {
- assert Ok(a) = uri.parse("/relative")
- assert Ok(b) = uri.parse("")
- uri.merge(a, b)
- |> should.equal(Error(Nil))
-
- assert Ok(a) = uri.parse("http://google.com/foo")
- assert Ok(b) = uri.parse("http://example.com/baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://google.com/foo")
- assert Ok(b) = uri.parse("http://example.com/.././bar/../../baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://google.com/foo")
- assert Ok(b) = uri.parse("//example.com/baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://google.com/foo")
- assert Ok(b) = uri.parse("//example.com/.././bar/../../../baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar")
- assert Ok(b) = uri.parse("/baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar")
- assert Ok(b) = uri.parse("baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/baz"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/")
- assert Ok(b) = uri.parse("baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/baz"))
-
- assert Ok(a) = uri.parse("http://example.com")
- assert Ok(b) = uri.parse("baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://example.com")
- assert Ok(b) = uri.parse("/.././bar/../../../baz")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/baz"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar")
- assert Ok(b) = uri.parse("")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/bar"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar")
- assert Ok(b) = uri.parse("#fragment")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/bar#fragment"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar")
- assert Ok(b) = uri.parse("?query")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/bar?query"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar?query1")
- assert Ok(b) = uri.parse("?query2")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/bar?query2"))
-
- assert Ok(a) = uri.parse("http://example.com/foo/bar?query")
- assert Ok(b) = uri.parse("")
- uri.merge(a, b)
- |> should.equal(uri.parse("http://example.com/foo/bar?query"))
+ }
+
+ pub fn path_only_uri_to_string_test() {
+ let test_uri = uri.Uri(None, None, None, None, "/", None, None)
+ should.equal(uri.to_string(test_uri), "/")
+ }
+
+ pub fn parse_query_string_test() {
+ assert Ok(parsed) = uri.parse_query("foo+bar=1&city=%C3%B6rebro")
+ should.equal(parsed, [#("foo bar", "1"), #("city", "örebro")])
+
+ // Duplicates keys not overridden
+ assert Ok(parsed) = uri.parse_query("a[]=1&a[]=2")
+
+ parsed
+ |> should.equal([#("a[]", "1"), #("a[]", "2")])
+ }
+
+ pub fn parse_empty_query_string_test() {
+ assert Ok(parsed) = uri.parse_query("")
+ should.equal(parsed, [])
+ }
+
+ pub fn parse_query_string_with_empty_test() {
+ uri.parse_query("present")
+ |> should.equal(Ok([#("present", "")]))
+ }
+
+ pub fn error_parsing_query_test() {
+ should.equal(uri.parse_query("%C2"), Error(Nil))
+ }
+
+ pub fn query_to_string_test() {
+ let query_string =
+ uri.query_to_string([#("foo bar", "1"), #("city", "örebro")])
+ should.equal(query_string, "foo+bar=1&city=%C3%B6rebro")
+ }
+
+ pub fn empty_query_to_string_test() {
+ let query_string = uri.query_to_string([])
+ should.equal(query_string, "")
+ }
+
+ fn percent_codec_fixtures() {
+ [
+ #(" ", "+"),
+ #(",", "%2C"),
+ #(";", "%3B"),
+ #(":", "%3A"),
+ #("!", "%21"),
+ #("?", "%3F"),
+ #("'", "%27"),
+ #("(", "%28"),
+ #(")", "%29"),
+ #("[", "%5B"),
+ #("@", "%40"),
+ #("/", "%2F"),
+ #("\\", "%5C"),
+ #("&", "%26"),
+ #("#", "%23"),
+ #("=", "%3D"),
+ #("~", "%7E"),
+ #("ñ", "%C3%B1"),
+ // Allowed chars
+ #("-", "-"),
+ #("_", "_"),
+ #(".", "."),
+ #("*", "*"),
+ #("100% great", "100%25+great"),
+ ]
+ }
+
+ pub fn percent_encode_test() {
+ percent_codec_fixtures()
+ |> list.map(fn(t) {
+ let #(a, b) = t
+ uri.percent_encode(a)
+ |> should.equal(b)
+ })
+ }
+
+ pub fn percent_encode_consistency_test() {
+ let k = "foo bar[]"
+ let v = "ñaña (,:*~)"
+
+ let query_string = uri.query_to_string([#(k, v)])
+
+ let encoded_key = uri.percent_encode(k)
+ let encoded_value = uri.percent_encode(v)
+ let manual_query_string = string.concat([encoded_key, "=", encoded_value])
+
+ should.equal(query_string, manual_query_string)
+ }
+
+ pub fn percent_decode_test() {
+ percent_codec_fixtures()
+ |> list.map(fn(t) {
+ let #(a, b) = t
+ uri.percent_decode(b)
+ |> should.equal(Ok(a))
+ })
+ }
+
+ pub fn percent_decode_consistency_test() {
+ let k = "foo+bar[]"
+ let v = "%C3%B6rebro"
+ let query = string.concat([k, "=", v])
+ assert Ok(parsed) = uri.parse_query(query)
+
+ assert Ok(decoded_key) = uri.percent_decode(k)
+ assert Ok(decoded_value) = uri.percent_decode(v)
+
+ should.equal(parsed, [#(decoded_key, decoded_value)])
+ }
+
+ pub fn parse_segments_test() {
+ should.equal(uri.path_segments("/"), [])
+ should.equal(uri.path_segments("/foo/bar"), ["foo", "bar"])
+ should.equal(uri.path_segments("////"), [])
+ should.equal(uri.path_segments("/foo//bar"), ["foo", "bar"])
+
+ should.equal(uri.path_segments("/."), [])
+ should.equal(uri.path_segments("/.foo"), [".foo"])
+
+ should.equal(uri.path_segments("/../bar"), ["bar"])
+ should.equal(uri.path_segments("../bar"), ["bar"])
+ should.equal(uri.path_segments("/foo/../bar"), ["bar"])
+ }
+
+ pub fn origin_test() {
+ assert Ok(parsed) = uri.parse("http://example.test/path?foo#bar")
+ uri.origin(parsed)
+ |> should.equal(Ok("http://example.test"))
+
+ assert Ok(parsed) = uri.parse("http://example.test:8080")
+ uri.origin(parsed)
+ |> should.equal(Ok("http://example.test:8080"))
+
+ assert Ok(parsed) = uri.parse("https://example.test")
+ uri.origin(parsed)
+ |> should.equal(Ok("https://example.test"))
+
+ assert Ok(parsed) = uri.parse("http:///path")
+ uri.origin(parsed)
+ |> should.equal(Ok("http://"))
+
+ assert Ok(parsed) = uri.parse("http://")
+ uri.origin(parsed)
+ |> should.equal(Ok("http://"))
+
+ assert Ok(parsed) = uri.parse("/path")
+ uri.origin(parsed)
+ |> should.equal(Error(Nil))
+
+ assert Ok(parsed) = uri.parse("file:///dev/null")
+ uri.origin(parsed)
+ |> should.equal(Error(Nil))
+ }
+
+ pub fn merge_test() {
+ assert Ok(a) = uri.parse("/relative")
+ assert Ok(b) = uri.parse("")
+ uri.merge(a, b)
+ |> should.equal(Error(Nil))
+
+ assert Ok(a) = uri.parse("http://google.com/foo")
+ assert Ok(b) = uri.parse("http://example.com/baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://google.com/foo")
+ assert Ok(b) = uri.parse("http://example.com/.././bar/../../baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://google.com/foo")
+ assert Ok(b) = uri.parse("//example.com/baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://google.com/foo")
+ assert Ok(b) = uri.parse("//example.com/.././bar/../../../baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar")
+ assert Ok(b) = uri.parse("/baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar")
+ assert Ok(b) = uri.parse("baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/baz"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/")
+ assert Ok(b) = uri.parse("baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/baz"))
+
+ assert Ok(a) = uri.parse("http://example.com")
+ assert Ok(b) = uri.parse("baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://example.com")
+ assert Ok(b) = uri.parse("/.././bar/../../../baz")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/baz"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar")
+ assert Ok(b) = uri.parse("")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/bar"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar")
+ assert Ok(b) = uri.parse("#fragment")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/bar#fragment"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar")
+ assert Ok(b) = uri.parse("?query")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/bar?query"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar?query1")
+ assert Ok(b) = uri.parse("?query2")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/bar?query2"))
+
+ assert Ok(a) = uri.parse("http://example.com/foo/bar?query")
+ assert Ok(b) = uri.parse("")
+ uri.merge(a, b)
+ |> should.equal(uri.parse("http://example.com/foo/bar?query"))
+ }
}