twister

The main module of twister, containing basically all of the relevant API.

Introduction

To use this library, you first need to create a Permutation, using one of the provided methods:

  1. Create it from a List of indexes directly, using the from_list function
  2. Create it using a builder pattern by first initializing it with blank, then adding indexes to the end one by one with add.

Examples

Creating a Permutation

Note : Inside of the Permutation data type, the list of indices is stored in reverse order. This is because when running one, the order is also reversed. So, instead of needlessly reversing the internal List, it’s just stored back to front.

Using a List of indices

// Create a `Permutation` from a `List` of indices
twister.from_list([1, 4, 2, 0, 3, 5])
// -> Permutation(False, Some(5), [5, 3, 0, 2, 4, 1])
//      This is the important part ^^^^^^^^^^^^^^^^

Using the builder

// Create a `Permutation` using a builder
twister.blank()
|> twister.add(1)
|> twister.add(4)
|> twister.add(2)
|> twister.add(0)
|> twister.add(3)
|> twister.add(5)
// -> Permutation(False, Some(5), [5, 3, 0, 2, 4, 1])
// Same as before, just more annoying. But sometimes useful

Using a Permutation

Using twister.run returns a Result(List(a), Nil);

let perm = twister.from_list([1, 4, 2, 0, 3, 5])
// Call it with run to get a `Result(List(a), Nil)`.
assert twister.run(perm, ["a", "b", "c", "d", "e", "f"])
  == Ok(["b", "e", "c", "a", "d", "f"])

Otherwise, you can use twister.run_default or twister.run_generate to replace missing elements if indices are outside of the bounds of the input List.

let perm = twister.from_list([1, 4, 2, 0, 3, 5])

assert twister.run_generate(perm, ["a", "b", "c", "d", "e"], int.to_string)
  == ["b", "e", "c", "a", "d", "5"]
//   Index outside the bounds  ^^^ replaced with generated value
assert twister.run_default(perm, ["a", "b", "c", "d", "e"], "")
  == ["b", "e", "c", "a", "d", ""]
//   Index outside the bounds  ^^ replaced with default value

Types

Type encoding a permutation.

To create, prefer using the initialization function from_list or the builder functions - first blank, then add.

To run a permutation on a given List, use the run or run_default functions.

To learn more, look at the documentation for the functions in question.

Note

Although the type is not opaque, you shouldn’t modify it yourself unless you really need to, and there’s no other way to achieve your goal.

pub type Permutation {
  Permutation(
    modulo: Bool,
    max_index: option.Option(Int),
    output: List(Int),
  )
}

Constructors

  • Permutation(
      modulo: Bool,
      max_index: option.Option(Int),
      output: List(Int),
    )

Values

pub fn add(perm: Permutation, index i: Int) -> Permutation

Add an index to the end of a Permutation.

This function is meant to be used after creating a blank Permutation using the blank function, but there’s nothing stopping you from using it to add elements to a Permutation created using the from_list function.

When later running a permutation on some List, that List must have a length more than or equal to the largest index in the list of indexes within, or it will return Error(Nil).

pub fn blank() -> Permutation

Create a new, blank Permutation.

This function is meant to be used as the starting point for constructing a Permutation using the builder pattern, by using the add function to add a new index at the end of the list of indexes.

pub fn compose(
  first: Permutation,
  with second: Permutation,
) -> Result(Permutation, Nil)

Transform two Permutations into a third, by executing the first one, then the second one.

Importantly, the first permutation must have an internal length of n + 1, where n is the largest index of the second, and its’ length will be that of the second one.

Lastly, the resulting Permutation will essentially be a new one, not inheriting the properties of the input ones (specifically the modulo from set_modulo).

pub fn from_list(indexes l: List(Int)) -> Permutation

Create a new Permutation from a given list of indexes.

When later running a permutation on some List, that List must have a length more than or equal to the largest index in the list of indexes within, or it will return Error(Nil).

pub fn run(
  perm: Permutation,
  on l: List(a),
) -> Result(List(a), Nil)

Run a created Permutation on some List.

This function returns a Result because there’s no guarantee that the provided List contains enough elements to build the permuted output.

For example, if I have a Permutation like [0, 2, 5] and I pass in ["a", "b"], there simply aren’t enough elements in the List to find the element at index 5, or even 2. So this function returns Error(Nil).

If you wish to guarantee that a Permutation always returns a List the exact same length as the List of specified indexes, use the run_default function, and choose a default value to return when the index is out of bounds.

pub fn run_default(
  perm: Permutation,
  on l: List(a),
  default default: a,
) -> List(a)

Run a created Permutation on some List.

This function always returns a List(a) by simply putting the provided default argument in the returned List whenever the requested index is out of bounds.

Note

If while creating the Permutation, the set_modulo function was used, this function will behave identically to run, as all of the indexes will definitely be within the bounds of the provided List.

pub fn run_generate(
  perm: Permutation,
  on l: List(a),
  generate fun: fn(Int) -> a,
) -> List(a)

Run a created Permutation on some List.

This function always returns a List(a) by simply generating a value in the returned List whenever the requested index is out of bounds, with the index in question as the input argument.

Note

If while creating the Permutation, the set_modulo function was used, this function will behave identically to run, as all of the indexes will definitely be within the bounds of the provided List.

pub fn set_modulo(perm: Permutation, to: Bool) -> Permutation
Search Document