Packages
gleam_stdlib
1.0.0
1.0.3
1.0.2
1.0.1
1.0.0
0.71.0
0.70.0
0.69.0
0.68.1
0.68.0
0.67.1
0.67.0
0.65.0
0.64.0
0.63.2
0.63.1
0.63.0
0.62.1
0.62.0
0.61.0
0.60.0
0.59.0
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.1
0.35.0
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.0
0.30.2
0.30.1
0.30.0
0.29.2
0.29.1
0.29.0
0.28.2
0.28.1
0.28.0
0.27.0
0.26.1
0.26.0
0.25.0
0.24.0
0.23.0
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.18.0-rc1
0.17.1
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.4.0-rc1
0.3.1
0.3.0
0.2.0
retired
A standard library for the Gleam programming language
Current section
Files
Jump to
Current section
Files
src/gleam/int.gleam
//// Functions for working with integers.
////
//// ## Division by zero
////
//// In Erlang division by zero results in a crash, however Gleam does not have
//// partial functions and operators in core so instead division by zero returns
//// zero, a behaviour taken from Pony, Coq, and Lean.
////
//// This may seem unexpected at first, but it is no less mathematically valid
//// than crashing or returning a special value. Division by zero is undefined
//// in mathematics.
import gleam/float
import gleam/order.{type Order}
/// Returns the absolute value of the input.
///
/// ## Examples
///
/// ```gleam
/// assert absolute_value(-12) == 12
/// ```
///
/// ```gleam
/// assert absolute_value(10) == 10
/// ```
///
pub fn absolute_value(x: Int) -> Int {
case x >= 0 {
True -> x
False -> x * -1
}
}
/// Returns the result of the base being raised to the power of the
/// exponent, as a `Float`.
///
/// ## Examples
///
/// ```gleam
/// assert power(2, -1.0) == Ok(0.5)
/// ```
///
/// ```gleam
/// assert power(2, 2.0) == Ok(4.0)
/// ```
///
/// ```gleam
/// assert power(8, 1.5) == Ok(22.627416997969522)
/// ```
///
/// ```gleam
/// assert 4 |> power(of: 2.0) == Ok(16.0)
/// ```
///
/// ```gleam
/// assert power(-1, 0.5) == Error(Nil)
/// ```
///
pub fn power(base: Int, of exponent: Float) -> Result(Float, Nil) {
base
|> to_float
|> float.power(exponent)
}
/// Returns the square root of the input as a `Float`.
///
/// ## Examples
///
/// ```gleam
/// assert square_root(4) == Ok(2.0)
/// ```
///
/// ```gleam
/// assert square_root(-16) == Error(Nil)
/// ```
///
pub fn square_root(x: Int) -> Result(Float, Nil) {
x
|> to_float
|> float.square_root()
}
/// Parses a given string as an int if possible.
///
/// ## Examples
///
/// ```gleam
/// assert parse("2") == Ok(2)
/// ```
///
/// ```gleam
/// assert parse("ABC") == Error(Nil)
/// ```
///
@external(erlang, "gleam_stdlib", "parse_int")
@external(javascript, "../gleam_stdlib.mjs", "parse_int")
pub fn parse(string: String) -> Result(Int, Nil)
/// Parses a given string as an int in a given base if possible.
/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.
///
/// ## Examples
///
/// ```gleam
/// assert base_parse("10", 2) == Ok(2)
/// ```
///
/// ```gleam
/// assert base_parse("30", 16) == Ok(48)
/// ```
///
/// ```gleam
/// assert base_parse("1C", 36) == Ok(48)
/// ```
///
/// ```gleam
/// assert base_parse("48", 1) == Error(Nil)
/// ```
///
/// ```gleam
/// assert base_parse("48", 37) == Error(Nil)
/// ```
///
pub fn base_parse(string: String, base: Int) -> Result(Int, Nil) {
case base >= 2 && base <= 36 {
True -> do_base_parse(string, base)
False -> Error(Nil)
}
}
@external(erlang, "gleam_stdlib", "int_from_base_string")
@external(javascript, "../gleam_stdlib.mjs", "int_from_base_string")
fn do_base_parse(a: String, b: Int) -> Result(Int, Nil)
/// Prints a given int to a string.
///
/// ## Examples
///
/// ```gleam
/// assert to_string(2) == "2"
/// ```
///
@external(erlang, "erlang", "integer_to_binary")
@external(javascript, "../gleam_stdlib.mjs", "to_string")
pub fn to_string(x: Int) -> String
/// Prints a given int to a string using the base number provided.
/// Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.
/// For common bases (2, 8, 16, 36), use the `to_baseN` functions.
///
/// ## Examples
///
/// ```gleam
/// assert to_base_string(2, 2) == Ok("10")
/// ```
///
/// ```gleam
/// assert to_base_string(48, 16) == Ok("30")
/// ```
///
/// ```gleam
/// assert to_base_string(48, 36) == Ok("1C")
/// ```
///
/// ```gleam
/// assert to_base_string(48, 1) == Error(Nil)
/// ```
///
/// ```gleam
/// assert to_base_string(48, 37) == Error(Nil)
/// ```
///
pub fn to_base_string(x: Int, base: Int) -> Result(String, Nil) {
case base >= 2 && base <= 36 {
True -> Ok(do_to_base_string(x, base))
False -> Error(Nil)
}
}
@external(erlang, "erlang", "integer_to_binary")
@external(javascript, "../gleam_stdlib.mjs", "int_to_base_string")
fn do_to_base_string(a: Int, b: Int) -> String
/// Prints a given int to a string using base-2.
///
/// ## Examples
///
/// ```gleam
/// assert to_base2(2) == "10"
/// ```
///
pub fn to_base2(x: Int) -> String {
do_to_base_string(x, 2)
}
/// Prints a given int to a string using base-8.
///
/// ## Examples
///
/// ```gleam
/// assert to_base8(15) == "17"
/// ```
///
pub fn to_base8(x: Int) -> String {
do_to_base_string(x, 8)
}
/// Prints a given int to a string using base-16.
///
/// ## Examples
///
/// ```gleam
/// assert to_base16(48) == "30"
/// ```
///
pub fn to_base16(x: Int) -> String {
do_to_base_string(x, 16)
}
/// Prints a given int to a string using base-36.
///
/// ## Examples
///
/// ```gleam
/// assert to_base36(48) == "1C"
/// ```
///
pub fn to_base36(x: Int) -> String {
do_to_base_string(x, 36)
}
/// Takes an int and returns its value as a float.
///
/// ## Examples
///
/// ```gleam
/// assert to_float(5) == 5.0
/// ```
///
/// ```gleam
/// assert to_float(0) == 0.0
/// ```
///
/// ```gleam
/// assert to_float(-3) == -3.0
/// ```
///
@external(erlang, "erlang", "float")
@external(javascript, "../gleam_stdlib.mjs", "identity")
pub fn to_float(x: Int) -> Float
/// Restricts an int between two bounds.
///
/// Note: If the `min` argument is larger than the `max` argument then they
/// will be swapped, so the minimum bound is always lower than the maximum
/// bound.
///
/// ## Examples
///
/// ```gleam
/// assert clamp(40, min: 50, max: 60) == 50
/// ```
///
/// ```gleam
/// assert clamp(40, min: 50, max: 30) == 40
/// ```
///
pub fn clamp(x: Int, min min_bound: Int, max max_bound: Int) -> Int {
case min_bound >= max_bound {
True -> x |> min(min_bound) |> max(max_bound)
False -> x |> min(max_bound) |> max(min_bound)
}
}
/// Compares two ints, returning an order.
///
/// ## Examples
///
/// ```gleam
/// assert compare(2, 3) == Lt
/// ```
///
/// ```gleam
/// assert compare(4, 3) == Gt
/// ```
///
/// ```gleam
/// assert 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 the smaller of the two.
///
/// ## Examples
///
/// ```gleam
/// assert min(2, 3) == 2
/// ```
///
pub fn min(a: Int, b: Int) -> Int {
case a < b {
True -> a
False -> b
}
}
/// Compares two ints, returning the larger of the two.
///
/// ## Examples
///
/// ```gleam
/// assert 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
///
/// ```gleam
/// assert is_even(2)
/// ```
///
/// ```gleam
/// assert !is_even(3)
/// ```
///
pub fn is_even(x: Int) -> Bool {
x % 2 == 0
}
/// Returns whether the value provided is odd.
///
/// ## Examples
///
/// ```gleam
/// assert is_odd(3)
/// ```
///
/// ```gleam
/// assert !is_odd(2)
/// ```
///
pub fn is_odd(x: Int) -> Bool {
x % 2 != 0
}
/// Returns the negative of the value provided.
///
/// ## Examples
///
/// ```gleam
/// assert negate(1) == -1
/// ```
///
pub fn negate(x: Int) -> Int {
-1 * x
}
/// Sums a list of ints.
///
/// ## Example
///
/// ```gleam
/// assert sum([1, 2, 3]) == 6
/// ```
///
pub fn sum(numbers: List(Int)) -> Int {
sum_loop(numbers, 0)
}
fn sum_loop(numbers: List(Int), initial: Int) -> Int {
case numbers {
[first, ..rest] -> sum_loop(rest, first + initial)
[] -> initial
}
}
/// Multiplies a list of ints and returns the product.
///
/// ## Example
///
/// ```gleam
/// assert product([2, 3, 4]) == 24
/// ```
///
pub fn product(numbers: List(Int)) -> Int {
product_loop(numbers, 1)
}
fn product_loop(numbers: List(Int), initial: Int) -> Int {
case numbers {
[first, ..rest] -> product_loop(rest, first * initial)
[] -> initial
}
}
/// Generates a random int between zero and the given maximum.
///
/// The lower number is inclusive, the upper number is exclusive.
///
/// ## Examples
///
/// ```gleam
/// random(10)
/// // -> 4
/// ```
///
/// ```gleam
/// random(1)
/// // -> 0
/// ```
///
/// ```gleam
/// random(-1)
/// // -> -1
/// ```
///
pub fn random(max: Int) -> Int {
{ float.random() *. to_float(max) }
|> float.floor
|> float.round
}
/// Performs a truncated integer division.
///
/// Returns division of the inputs as a `Result`: If the given divisor equals
/// `0`, this function returns an `Error`.
///
/// ## Examples
///
/// ```gleam
/// assert divide(0, 1) == Ok(0)
/// ```
///
/// ```gleam
/// assert divide(1, 0) == Error(Nil)
/// ```
///
/// ```gleam
/// assert divide(5, 2) == Ok(2)
/// ```
///
/// ```gleam
/// assert divide(-99, 2) == Ok(-49)
/// ```
///
pub fn divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) {
case divisor {
0 -> Error(Nil)
divisor -> Ok(dividend / divisor)
}
}
/// Computes the remainder of an integer division of inputs as a `Result`.
///
/// Returns division of the inputs as a `Result`: If the given divisor equals
/// `0`, this function returns an `Error`.
///
/// Most of the time you will want to use the `%` operator instead of this
/// function.
///
/// ## Examples
///
/// ```gleam
/// assert remainder(3, 2) == Ok(1)
/// ```
///
/// ```gleam
/// assert remainder(1, 0) == Error(Nil)
/// ```
///
/// ```gleam
/// assert remainder(10, -1) == Ok(0)
/// ```
///
/// ```gleam
/// assert remainder(13, by: 3) == Ok(1)
/// ```
///
/// ```gleam
/// assert remainder(-13, by: 3) == Ok(-1)
/// ```
///
/// ```gleam
/// assert remainder(13, by: -3) == Ok(1)
/// ```
///
/// ```gleam
/// assert remainder(-13, by: -3) == Ok(-1)
/// ```
///
pub fn remainder(dividend: Int, by divisor: Int) -> Result(Int, Nil) {
case divisor {
0 -> Error(Nil)
divisor -> Ok(dividend % divisor)
}
}
/// Computes the modulo of an integer division of inputs as a `Result`.
///
/// Returns division of the inputs as a `Result`: If the given divisor equals
/// `0`, this function returns an `Error`.
///
/// Note that this is different from `int.remainder` and `%` in that the
/// computed value will always have the same sign as the `divisor`.
///
/// ## Examples
///
/// ```gleam
/// assert modulo(3, 2) == Ok(1)
/// ```
///
/// ```gleam
/// assert modulo(1, 0) == Error(Nil)
/// ```
///
/// ```gleam
/// assert modulo(10, -1) == Ok(0)
/// ```
///
/// ```gleam
/// assert modulo(13, by: 3) == Ok(1)
/// ```
///
/// ```gleam
/// assert modulo(-13, by: 3) == Ok(2)
/// ```
///
/// ```gleam
/// assert modulo(13, by: -3) == Ok(-2)
/// ```
///
pub fn modulo(dividend: Int, by divisor: Int) -> Result(Int, Nil) {
case divisor {
0 -> Error(Nil)
_ -> {
let remainder = dividend % divisor
case remainder * divisor < 0 {
True -> Ok(remainder + divisor)
False -> Ok(remainder)
}
}
}
}
/// Performs a *floored* integer division, which means that the result will
/// always be rounded towards negative infinity.
///
/// If you want to perform truncated integer division (rounding towards zero),
/// use `int.divide()` or the `/` operator instead.
///
/// Returns division of the inputs as a `Result`: If the given divisor equals
/// `0`, this function returns an `Error`.
///
/// ## Examples
///
/// ```gleam
/// assert floor_divide(1, 0) == Error(Nil)
/// ```
///
/// ```gleam
/// assert floor_divide(5, 2) == Ok(2)
/// ```
///
/// ```gleam
/// assert floor_divide(6, -4) == Ok(-2)
/// ```
///
/// ```gleam
/// assert floor_divide(-99, 2) == Ok(-50)
/// ```
///
pub fn floor_divide(dividend: Int, by divisor: Int) -> Result(Int, Nil) {
case divisor {
0 -> Error(Nil)
divisor ->
case dividend * divisor < 0 && dividend % divisor != 0 {
True -> Ok(dividend / divisor - 1)
False -> Ok(dividend / divisor)
}
}
}
/// Adds two integers together.
///
/// It's the function equivalent of the `+` operator.
/// This function is useful in higher order functions or pipes.
///
/// ## Examples
///
/// ```gleam
/// assert add(1, 2) == 3
/// ```
///
/// ```gleam
/// import gleam/list
/// assert list.fold([1, 2, 3], 0, add) == 6
/// ```
///
/// ```gleam
/// assert 3 |> add(2) == 5
/// ```
///
pub fn add(a: Int, b: Int) -> Int {
a + b
}
/// Multiplies two integers together.
///
/// It's the function equivalent of the `*` operator.
/// This function is useful in higher order functions or pipes.
///
/// ## Examples
///
/// ```gleam
/// assert multiply(2, 4) == 8
/// ```
///
/// ```gleam
/// import gleam/list
///
/// assert list.fold([2, 3, 4], 1, multiply) == 24
/// ```
///
/// ```gleam
/// assert 3 |> multiply(2) == 6
/// ```
///
pub fn multiply(a: Int, b: Int) -> Int {
a * b
}
/// Subtracts one int from another.
///
/// It's the function equivalent of the `-` operator.
/// This function is useful in higher order functions or pipes.
///
/// ## Examples
///
/// ```gleam
/// assert subtract(3, 1) == 2
/// ```
///
/// ```gleam
/// import gleam/list
///
/// assert list.fold([1, 2, 3], 10, subtract) == 4
/// ```
///
/// ```gleam
/// assert 3 |> subtract(2) == 1
/// ```
///
/// ```gleam
/// assert 3 |> subtract(2, _) == -1
/// ```
///
pub fn subtract(a: Int, b: Int) -> Int {
a - b
}
/// Calculates the bitwise AND of its arguments.
///
/// Most the time you should use the bit array syntaxes instead of manipulating
/// bits as ints with bitwise functions.
///
/// ## Target specific behaviour
///
/// The exact behaviour of this function depends on the target platform.
/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it
/// is equivalent to bitwise operations on big-ints. If you need to avoid the
/// overhead of big-ints on JavaScript use bit arrays or another package that
/// provides faster bitwise operations.
///
@external(erlang, "erlang", "band")
@external(javascript, "../gleam_stdlib.mjs", "bitwise_and")
pub fn bitwise_and(x: Int, y: Int) -> Int
/// Calculates the bitwise NOT of its argument.
///
/// Most the time you should use the bit array syntaxes instead of manipulating
/// bits as ints with bitwise functions.
///
/// ## Target specific behaviour
///
/// The exact behaviour of this function depends on the target platform.
/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it
/// is equivalent to bitwise operations on big-ints. If you need to avoid the
/// overhead of big-ints on JavaScript use bit arrays or another package that
/// provides faster bitwise operations.
///
@external(erlang, "erlang", "bnot")
@external(javascript, "../gleam_stdlib.mjs", "bitwise_not")
pub fn bitwise_not(x: Int) -> Int
/// Calculates the bitwise OR of its arguments.
///
/// Most the time you should use the bit array syntaxes instead of manipulating
/// bits as ints with bitwise functions.
///
/// ## Target specific behaviour
///
/// The exact behaviour of this function depends on the target platform.
/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it
/// is equivalent to bitwise operations on big-ints. If you need to avoid the
/// overhead of big-ints on JavaScript use bit arrays or another package that
/// provides faster bitwise operations.
///
@external(erlang, "erlang", "bor")
@external(javascript, "../gleam_stdlib.mjs", "bitwise_or")
pub fn bitwise_or(x: Int, y: Int) -> Int
/// Calculates the bitwise XOR of its arguments.
///
/// Most the time you should use the bit array syntaxes instead of manipulating
/// bits as ints with bitwise functions.
///
/// ## Target specific behaviour
///
/// The exact behaviour of this function depends on the target platform.
/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it
/// is equivalent to bitwise operations on big-ints. If you need to avoid the
/// overhead of big-ints on JavaScript use bit arrays or another package that
/// provides faster bitwise operations.
///
@external(erlang, "erlang", "bxor")
@external(javascript, "../gleam_stdlib.mjs", "bitwise_exclusive_or")
pub fn bitwise_exclusive_or(x: Int, y: Int) -> Int
/// Calculates the result of an arithmetic left bitshift.
///
/// Most the time you should use the bit array syntaxes instead of manipulating
/// bits as ints with bitwise functions.
///
/// ## Target specific behaviour
///
/// The exact behaviour of this function depends on the target platform.
/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it
/// is equivalent to bitwise operations on big-ints. If you need to avoid the
/// overhead of big-ints on JavaScript use bit arrays or another package that
/// provides faster bitwise operations.
///
@external(erlang, "erlang", "bsl")
@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_left")
pub fn bitwise_shift_left(x: Int, y: Int) -> Int
/// Calculates the result of an arithmetic right bitshift.
///
/// Most the time you should use the bit array syntaxes instead of manipulating
/// bits as ints with bitwise functions.
///
/// ## Target specific behaviour
///
/// The exact behaviour of this function depends on the target platform.
/// On Erlang it is equivalent to bitwise operations on ints, on JavaScript it
/// is equivalent to bitwise operations on big-ints. If you need to avoid the
/// overhead of big-ints on JavaScript use bit arrays or another package that
/// provides faster bitwise operations.
///
@external(erlang, "erlang", "bsr")
@external(javascript, "../gleam_stdlib.mjs", "bitwise_shift_right")
pub fn bitwise_shift_right(x: Int, y: Int) -> Int
/// Run a function for each int between ints `from` and `to`.
///
/// `from` is inclusive, and `to` is exclusive.
///
/// ## Examples
///
/// ```gleam
/// assert
/// range(from: 0, to: 3, with: "", run: fn(acc, i) {
/// acc <> to_string(i)
/// })
/// == "012"
/// ```
///
/// ```gleam
/// assert range(from: 1, to: -2, with: [], run: list.prepend) == [-1, 0, 1]
/// ```
///
pub fn range(
from start: Int,
to stop: Int,
with acc: acc,
run reducer: fn(acc, Int) -> acc,
) -> acc {
let increment = case start < stop {
True -> 1
False -> -1
}
range_loop(start, stop, increment, acc, reducer)
}
fn range_loop(
current: Int,
stop: Int,
increment: Int,
acc: acc,
reducer: fn(acc, Int) -> acc,
) -> acc {
case current == stop {
True -> acc
False -> {
let acc = reducer(acc, current)
let current = current + increment
range_loop(current, stop, increment, acc, reducer)
}
}
}