API reference

fp.functions

fp.functions provides eager pipelines, function composition and partial application. Use pipe to apply a sequence of functions now, flow or compose to build a function for later calls, and partial to bind leading arguments. The pipeline tutorial starts with a complete program.

Pipelines, compositions, argument flipping and partial application.

Use pipe(value, f, g) to apply stages now, flow(f, g) or compose(g, f) to build a reusable composition, and piped(value).then(f).get() to chain any number of stages one call at a time. flip swaps two arguments and partial binds leading arguments.

A stage is a plain function, a closure promoted with as_unary, or a library value that implements Unary, such as a Partial or a Composition. Each stage's input must equal the previous stage's result. Values move from stage to stage without copies, stages are borrowed, and a raised error stops the chain with its own type; a returned Result is ordinary data.

Summary

Name Kind Summary
compose function Compose stages right to left; nothing runs until the result is called.
flip function Swap the two arguments of a binary callable, keeping its receiver modes.
flow function Compose stages left to right; nothing runs until the result is called.
identity function Return value unchanged, moving it.
partial function Bind a plain function's first argument; call the result with the rest.
pipe function Apply stages to value left to right and return the last result.
piped function Start an eager chained pipeline: piped(value).then(f).then(g).get().
Composition struct A stored chain of stages, returned by flow and compose.
Flipped struct A binary callable called with its two arguments swapped, returned by flip.
FlippedFunction struct A plain function called with its first two arguments swapped, returned by flip.
Identity struct The unary identity on T, returned by flow[T]() and compose[T]().
Partial struct A plain function with copies of its leading arguments, returned by partial.
Piped struct A value in an eager chained pipeline, started by piped(value).
as_unary re-export Re-exported from fp.callables.

Functions

compose

Source: fp/functions/composition.mojo

def compose[*Fs](
    var *functions: *Fs,
) -> Composition[True, _Arity[Fs[Fs.length - 1]], *Fs] where Fs.length >= 2

Compose stages right to left; nothing runs until the result is called.

compose(h, g, f)(x) is h(g(f(x))): the last argument runs first and may take zero, one or two arguments. Plain functions, library values and promoted closures are accepted as in flow. A mismatched stage is reported by its position in the run order and its argument position.

Limitations

At most eight plain functions per call, and plain functions mixed with library values are promoted with as_unary, as in pipe.

Parameters

  • *Fs (Movable & Deinitable): The stage types, in the order they are passed.

Arguments

  • *functions (var *Fs): The stages, moved into the composition.

Returns

Composition[...]: A Composition that runs the stages right to left.

23 more overloads

Return the identity on `T`: a composition with no stages.

def compose[T]() -> Identity[T]

Return one stage unchanged, with all its capabilities.

def compose[F](var function: F) -> F

Store 2 plain functions, applied right to left.

def compose[A0, A1, A2, P1, E0, E1, //](
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 3 plain functions, applied right to left.

def compose[A0, A1, A2, A3, P1, P2, E0, E1, E2, //](
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 4 plain functions, applied right to left.

def compose[A0, A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 5 plain functions, applied right to left.

def compose[A0, A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 6 plain functions, applied right to left.

def compose[
    A0, A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5, //,
](
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 7 plain functions, applied right to left.

def compose[
    A0, A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3, E4,
    E5, E6, //,
](
    f6: def(var P6) raises E6 thin -> A7,
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P6, A7, E6], _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 8 plain functions, applied right to left.

def compose[
    A0, A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1, E2,
    E3, E4, E5, E6, E7, //,
](
    f7: def(var P7) raises E7 thin -> A8,
    f6: def(var P6) raises E6 thin -> A7,
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var A0) raises E0 thin -> A1,
) -> Composition[True, 1, _Thin1F[P7, A8, E7], _Thin1F[P6, A7, E6], _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin1F[A0, A1, E0]]

Store 2 plain functions, applied right to left.

def compose[A1, A2, P1, E0, E1, //](
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 3 plain functions, applied right to left.

def compose[A1, A2, A3, P1, P2, E0, E1, E2, //](
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 4 plain functions, applied right to left.

def compose[A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 5 plain functions, applied right to left.

def compose[A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 6 plain functions, applied right to left.

def compose[
    A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5, //,
](
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 7 plain functions, applied right to left.

def compose[
    A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3, E4, E5,
    E6, //,
](
    f6: def(var P6) raises E6 thin -> A7,
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P6, A7, E6], _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 8 plain functions, applied right to left.

def compose[
    A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1, E2, E3,
    E4, E5, E6, E7, //,
](
    f7: def(var P7) raises E7 thin -> A8,
    f6: def(var P6) raises E6 thin -> A7,
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def() raises E0 thin -> A1,
) -> Composition[True, 0, _Thin1F[P7, A8, E7], _Thin1F[P6, A7, E6], _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin0F[A1, E0]]

Store 2 plain functions, applied right to left.

def compose[B0, B1, A1, A2, P1, E0, E1, //](
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

Store 3 plain functions, applied right to left.

def compose[B0, B1, A1, A2, A3, P1, P2, E0, E1, E2, //](
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

Store 4 plain functions, applied right to left.

def compose[B0, B1, A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

Store 5 plain functions, applied right to left.

def compose[B0, B1, A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

Store 6 plain functions, applied right to left.

def compose[
    B0, B1, A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5,
    //,
](
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

Store 7 plain functions, applied right to left.

def compose[
    B0, B1, A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3,
    E4, E5, E6, //,
](
    f6: def(var P6) raises E6 thin -> A7,
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P6, A7, E6], _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

Store 8 plain functions, applied right to left.

def compose[
    B0, B1, A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1,
    E2, E3, E4, E5, E6, E7, //,
](
    f7: def(var P7) raises E7 thin -> A8,
    f6: def(var P6) raises E6 thin -> A7,
    f5: def(var P5) raises E5 thin -> A6,
    f4: def(var P4) raises E4 thin -> A5,
    f3: def(var P3) raises E3 thin -> A4,
    f2: def(var P2) raises E2 thin -> A3,
    f1: def(var P1) raises E1 thin -> A2,
    f0: def(var B0, var B1) raises E0 thin -> A1,
) -> Composition[True, 2, _Thin1F[P7, A8, E7], _Thin1F[P6, A7, E6], _Thin1F[P5, A6, E5], _Thin1F[P4, A5, E4], _Thin1F[P3, A4, E3], _Thin1F[P2, A3, E2], _Thin1F[P1, A2, E1], _Thin2F[B0, B1, A1, E0]]

flip

Source: fp/functions/flipped.mojo

def flip[F: BinaryContract & Movable & Deinitable](
    var function: F,
) -> Flipped[F]

Swap the two arguments of a binary callable, keeping its receiver modes.

Parameters

  • F (BinaryContract & Movable & Deinitable): The callable's type, a Binary, MutableBinary or OnceBinary.

Arguments

  • function (var F): The binary library value to flip, moved in.

Returns

Flipped[F]: A Flipped that calls function(second, first).

def flip[A0, A1, R, E, Rs: TypeList[Trait=_Swap, ...], //](
    function: def(var a0: A0, var a1: A1, *args: *Rs) raises E thin -> R,
) -> FlippedFunction[R, E, A0, A1, Rs]

Swap the first two arguments of a plain function.

flip(f)(a, b, rest...) calls f(b, a, rest...) and keeps f's error type.

Limitations

f must be a plain function (no captures); flip a closure by writing another closure. Keyword arguments are not forwarded.

Parameters

  • A0 (Movable & Deinitable, inferred): The function's first parameter type.
  • A1 (Movable & Deinitable, inferred): The function's second parameter type.
  • R (Movable & Deinitable, inferred): The function's result type.
  • E (Movable & Deinitable, inferred): The function's error type, Never for a pure function.
  • Rs (TypeList[...], inferred): The types of the remaining parameters.

Arguments

  • function (def(var a0: A0, var a1: A1, *args: *Rs) raises E thin -> R): The plain function to flip.

Returns

FlippedFunction[R, E, A0, A1, Rs]: A FlippedFunction that calls function(second, first, rest...).

flow

Source: fp/functions/composition.mojo

def flow[*Fs](
    var *functions: *Fs,
) -> Composition[False, _Arity[Fs[0]], *Fs] where Fs.length >= 2

Compose stages left to right; nothing runs until the result is called.

flow(f, g, h)(x) is h(g(f(x))). Two to eight plain functions are accepted as they are; library values such as partials, compositions and flipped functions, and closures promoted with as_unary, are accepted in any number. The first stage may take zero, one or two arguments; every later stage takes the previous result, or the call does not compile, with an error that names the stage.

Limitations

At most eight plain functions per call, and plain functions mixed with library values are promoted with as_unary, as in pipe.

Parameters

  • *Fs (Movable & Deinitable): The stage types.

Arguments

  • *functions (var *Fs): The stages, moved into the composition.

Returns

Composition[...]: A Composition that runs the stages left to right.

23 more overloads

Return the identity on `T`: a composition with no stages.

def flow[T]() -> Identity[T]

Return one stage unchanged, with all its capabilities.

def flow[F](var function: F) -> F

Store 2 plain functions, applied left to right.

def flow[A0, A1, A2, P1, E0, E1, //](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1]]

Store 3 plain functions, applied left to right.

def flow[A0, A1, A2, A3, P1, P2, E0, E1, E2, //](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2]]

Store 4 plain functions, applied left to right.

def flow[A0, A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3]]

Store 5 plain functions, applied left to right.

def flow[A0, A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4]]

Store 6 plain functions, applied left to right.

def flow[
    A0, A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5, //,
](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5]]

Store 7 plain functions, applied left to right.

def flow[
    A0, A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3, E4,
    E5, E6, //,
](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5], _Thin1F[P6, A7, E6]]

Store 8 plain functions, applied left to right.

def flow[
    A0, A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1, E2,
    E3, E4, E5, E6, E7, //,
](
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
    f7: def(var P7) raises E7 thin -> A8,
) -> Composition[False, 1, _Thin1F[A0, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5], _Thin1F[P6, A7, E6], _Thin1F[P7, A8, E7]]

Store 2 plain functions, applied left to right.

def flow[A1, A2, P1, E0, E1, //](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1]]

Store 3 plain functions, applied left to right.

def flow[A1, A2, A3, P1, P2, E0, E1, E2, //](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2]]

Store 4 plain functions, applied left to right.

def flow[A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3]]

Store 5 plain functions, applied left to right.

def flow[A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4]]

Store 6 plain functions, applied left to right.

def flow[
    A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5, //,
](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5]]

Store 7 plain functions, applied left to right.

def flow[
    A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3, E4, E5,
    E6, //,
](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5], _Thin1F[P6, A7, E6]]

Store 8 plain functions, applied left to right.

def flow[
    A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1, E2, E3,
    E4, E5, E6, E7, //,
](
    f0: def() raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
    f7: def(var P7) raises E7 thin -> A8,
) -> Composition[False, 0, _Thin0F[A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5], _Thin1F[P6, A7, E6], _Thin1F[P7, A8, E7]]

Store 2 plain functions, applied left to right.

def flow[B0, B1, A1, A2, P1, E0, E1, //](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1]]

Store 3 plain functions, applied left to right.

def flow[B0, B1, A1, A2, A3, P1, P2, E0, E1, E2, //](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2]]

Store 4 plain functions, applied left to right.

def flow[B0, B1, A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3]]

Store 5 plain functions, applied left to right.

def flow[B0, B1, A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4]]

Store 6 plain functions, applied left to right.

def flow[
    B0, B1, A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5,
    //,
](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5]]

Store 7 plain functions, applied left to right.

def flow[
    B0, B1, A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3,
    E4, E5, E6, //,
](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5], _Thin1F[P6, A7, E6]]

Store 8 plain functions, applied left to right.

def flow[
    B0, B1, A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1,
    E2, E3, E4, E5, E6, E7, //,
](
    f0: def(var B0, var B1) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
    f7: def(var P7) raises E7 thin -> A8,
) -> Composition[False, 2, _Thin2F[B0, B1, A1, E0], _Thin1F[P1, A2, E1], _Thin1F[P2, A3, E2], _Thin1F[P3, A4, E3], _Thin1F[P4, A5, E4], _Thin1F[P5, A6, E5], _Thin1F[P6, A7, E6], _Thin1F[P7, A8, E7]]

identity

Source: fp/functions/pipeline.mojo

def identity[T: Movable](var value: T) -> T

Return value unchanged, moving it.

Parameters

  • T (Movable): The value's type.

Arguments

  • value (var T): The value, consumed.

Returns

T: value itself; nothing is copied.

partial

Source: fp/functions/partial.mojo

def partial[A0: _Bound, R, E, Rs: TypeList[Trait=_Rest, ...], //](
    function: def(var a0: A0, *args: *Rs) raises E thin -> R,
    a0: A0,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0](), Rs]

Bind a plain function's first argument; call the result with the rest.

partial(f, a)(b, c) calls f(a, b, c). The overloads bind zero to eight leading arguments, as in partial(f, a, b). Construction copies each bound argument once and never calls f; every call passes f fresh copies, and the remaining arguments are borrowed. The result keeps f's error type.

Limitations

f must be a plain function (no captures) whose remaining parameters are read, not owned or mut; bound values must be Copyable; and a Partial cannot be the target of another partial. Keyword binding, reordering and the other cases are written as a closure.

Parameters

  • A0 (inferred): The bound argument's type; it must be Copyable.
  • R (Movable & Deinitable, inferred): The function's result type.
  • E (Movable & Deinitable, inferred): The function's error type, Never for a pure function.
  • Rs (TypeList[...], inferred): The types of the remaining parameters.

Arguments

  • function (def(var a0: A0, *args: *Rs) raises E thin -> R): The plain function.
  • a0 (A0): The value to bind, copied.

Returns

Partial[...]: A Partial that calls function(a0, rest...).

8 more overloads

Store a native function without binding arguments.

def partial[R, E, Rs: TypeList[Trait=_Rest, ...], //](
    function: def(*args: *Rs) raises E thin -> R,
) -> Partial[R, E, TypeList.of[Trait=_Bound](), Rs]

Bind the first two arguments.

def partial[A0: _Bound, A1: _Bound, R, E, Rs: TypeList[Trait=_Rest, ...], //](
    function: def(var a0: A0, var a1: A1, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1](), Rs]

Bind the first three arguments.

def partial[
    A0: _Bound, A1: _Bound, A2: _Bound, R, E, Rs: TypeList[Trait=_Rest, ...],
    //,
](
    function: def(var a0: A0, var a1: A1, var a2: A2, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
    a2: A2,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1, A2](), Rs]

Bind the first four arguments.

def partial[
    A0: _Bound, A1: _Bound, A2: _Bound, A3: _Bound, R, E, Rs:
    TypeList[Trait=_Rest, ...], //,
](
    function: def(var a0: A0, var a1: A1, var a2: A2, var a3: A3, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
    a2: A2,
    a3: A3,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1, A2, A3](), Rs]

Bind the first five arguments.

def partial[
    A0: _Bound, A1: _Bound, A2: _Bound, A3: _Bound, A4: _Bound, R, E, Rs:
    TypeList[Trait=_Rest, ...], //,
](
    function: def(var a0: A0, var a1: A1, var a2: A2, var a3: A3, var a4: A4, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
    a2: A2,
    a3: A3,
    a4: A4,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1, A2, A3, A4](), Rs]

Bind the first six arguments.

def partial[
    A0: _Bound, A1: _Bound, A2: _Bound, A3: _Bound, A4: _Bound, A5: _Bound, R,
    E, Rs: TypeList[Trait=_Rest, ...], //,
](
    function: def(var a0: A0, var a1: A1, var a2: A2, var a3: A3, var a4: A4, var a5: A5, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
    a2: A2,
    a3: A3,
    a4: A4,
    a5: A5,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1, A2, A3, A4, A5](), Rs]

Bind the first seven arguments.

def partial[
    A0: _Bound, A1: _Bound, A2: _Bound, A3: _Bound, A4: _Bound, A5: _Bound, A6:
    _Bound, R, E, Rs: TypeList[Trait=_Rest, ...], //,
](
    function: def(var a0: A0, var a1: A1, var a2: A2, var a3: A3, var a4: A4, var a5: A5, var a6: A6, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
    a2: A2,
    a3: A3,
    a4: A4,
    a5: A5,
    a6: A6,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1, A2, A3, A4, A5, A6](), Rs]

Bind the first eight arguments.

def partial[
    A0: _Bound, A1: _Bound, A2: _Bound, A3: _Bound, A4: _Bound, A5: _Bound, A6:
    _Bound, A7: _Bound, R, E, Rs: TypeList[Trait=_Rest, ...], //,
](
    function: def(var a0: A0, var a1: A1, var a2: A2, var a3: A3, var a4: A4, var a5: A5, var a6: A6, var a7: A7, *args: *Rs) raises E thin -> R,
    a0: A0,
    a1: A1,
    a2: A2,
    a3: A3,
    a4: A4,
    a5: A5,
    a6: A6,
    a7: A7,
) -> Partial[R, E, TypeList.of[Trait=_Bound, A0, A1, A2, A3, A4, A5, A6, A7](), Rs]

pipe

Source: fp/functions/pipeline.mojo

def pipe[A, //, *Fs](
    var value: A,
    *functions: *Fs,
) raises _Plan[*Fs].Failure -> _PipelineResult[A, _Plan[*Fs].Results] where Fs.length >= 2

Apply stages to value left to right and return the last result.

Each stage runs once, in order, and receives the previous stage's result as an owned value; tuples and Result values pass whole. Two to eight plain functions are accepted as they are, pipe(value, parse, check, render); library values such as partials and compositions, and closures promoted with as_unary, are accepted in any number. A stage whose input is not the previous result is a compile error that names the stage. pipe[E=Failure] states the common error, and pipe[Results, E] every result type.

Limitations

At most eight plain functions per call, because Mojo 1.1 cannot read a function's signature from a variadic pack: nest calls, group stages with flow, or chain them with piped. Plain functions mixed with library values are promoted with as_unary. Stages that raise different error types are mapped to one type first.

Parameters

  • A (Movable & Deinitable, inferred): The input type.
  • *Fs (Movable & Deinitable): The stage types.

Arguments

  • value (var A): The input, consumed.
  • *functions (*Fs): The stages, borrowed, in the order they run.

Returns

The last stage's result.

Raises

The error type that every raising stage declares; a pipeline of pure stages does not raise.

13 more overloads

Return `value` unchanged: a pipeline with no stages.

def pipe[T: Movable](var value: T) -> T

Apply one pure stage: a plain function or a closure.

def pipe[A: Movable, R: Movable, //, F: def(var A) -> R](
    var value: A,
    function: F,
) -> R

Apply one raising stage; its error type is kept.

def pipe[A: Movable, R: Movable, E: AnyType, //, F: def(var A) raises E -> R](
    var value: A,
    function: F,
) raises E -> R

Apply one library `Unary` value, such as a partial or a composition.

def pipe[A, F: Unary](
    var value: A,
    function: F,
) raises F.Error -> F.Out where F.Arg == A

Apply stages with every result type stated: `pipe[Results, E](value, *stages)`.

def pipe[
    A, //, Results: TypeList[Trait=Movable & Deinitable, ...], E: Movable &
    Deinitable = Never, *Fs,
](
    var value: A,
    *functions: *Fs,
) raises E -> _PipelineResult[A, Results]

Apply stages with their common error stated: `pipe[E=Failure](value, *stages)`.

def pipe[A, //, E, *Fs](
    var value: A,
    *functions: *Fs,
) raises E -> _PipelineResult[A, _Plan[*Fs].Results] where Fs.length >= 2

Apply 2 plain functions in order.

def pipe[A0, A1, A2, P1, E0, E1, //](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
) raises _CommonError[E0, E1] -> A2

Apply 3 plain functions in order.

def pipe[A0, A1, A2, A3, P1, P2, E0, E1, E2, //](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
) raises _CommonError[_CommonError[E0, E1], E2] -> A3

Apply 4 plain functions in order.

def pipe[A0, A1, A2, A3, A4, P1, P2, P3, E0, E1, E2, E3, //](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
) raises _CommonError[_CommonError[_CommonError[E0, E1], E2], E3] -> A4

Apply 5 plain functions in order.

def pipe[A0, A1, A2, A3, A4, A5, P1, P2, P3, P4, E0, E1, E2, E3, E4, //](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
) raises _CommonError[_CommonError[_CommonError[_CommonError[E0, E1], E2], E3], E4] -> A5

Apply 6 plain functions in order.

def pipe[
    A0, A1, A2, A3, A4, A5, A6, P1, P2, P3, P4, P5, E0, E1, E2, E3, E4, E5, //,
](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
) raises _CommonError[_CommonError[_CommonError[_CommonError[_CommonError[E0, E1], E2], E3], E4], E5] -> A6

Apply 7 plain functions in order.

def pipe[
    A0, A1, A2, A3, A4, A5, A6, A7, P1, P2, P3, P4, P5, P6, E0, E1, E2, E3, E4,
    E5, E6, //,
](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
) raises _CommonError[_CommonError[_CommonError[_CommonError[_CommonError[_CommonError[E0, E1], E2], E3], E4], E5], E6] -> A7

Apply 8 plain functions in order.

def pipe[
    A0, A1, A2, A3, A4, A5, A6, A7, A8, P1, P2, P3, P4, P5, P6, P7, E0, E1, E2,
    E3, E4, E5, E6, E7, //,
](
    var value: A0,
    f0: def(var A0) raises E0 thin -> A1,
    f1: def(var P1) raises E1 thin -> A2,
    f2: def(var P2) raises E2 thin -> A3,
    f3: def(var P3) raises E3 thin -> A4,
    f4: def(var P4) raises E4 thin -> A5,
    f5: def(var P5) raises E5 thin -> A6,
    f6: def(var P6) raises E6 thin -> A7,
    f7: def(var P7) raises E7 thin -> A8,
) raises _CommonError[_CommonError[_CommonError[_CommonError[_CommonError[_CommonError[_CommonError[E0, E1], E2], E3], E4], E5], E6], E7] -> A8

piped

Source: fp/functions/pipeline.mojo

def piped[T](var value: T) -> Piped[T]

Start an eager chained pipeline: piped(value).then(f).then(g).get().

The chain returns g(f(value)). Each stage runs once, when its then is called, so a chain has no limit on its length, and closures need no as_unary. Unlike pipe, the stages need not share one error type: each then raises its own.

Parameters

  • T (Movable & Deinitable): The input type.

Arguments

  • value (var T): The input, consumed.

Returns

Piped[T]: A chain holding value.

Structs

Composition

Source: fp/functions/composition.mojo

struct Composition[reverse: Bool, arity: Int, *Fs](
    Movable,
    Copyable where Fs.map[_Cell]().all_conforms_to[Copyable](),
    ThunkContract where arity == 0,
    UnaryContract where arity == 1,
    BinaryContract where arity == 2,
    Thunk where arity == 0 and _AllShared[Fs],
    MutableThunk where arity == 0 and _AllMutable[Fs],
    OnceThunk where arity == 0 and _AllOnce[Fs],
    Unary where arity == 1 and _AllShared[Fs],
    MutableUnary where arity == 1 and _AllMutable[Fs],
    OnceUnary where arity == 1 and _AllOnce[Fs],
    Binary where arity == 2 and _AllShared[Fs],
    MutableBinary where arity == 2 and _AllMutable[Fs],
    OnceBinary where arity == 2 and _AllOnce[Fs],
)

A stored chain of stages, returned by flow and compose.

The first stage to run may take zero, one or two arguments (a Thunk, Unary or Binary, including plain functions and closures promoted with as_unary); every later stage takes the previous result. Calling the composition runs each stage once, in order, and a raised error stops it. It is itself a Thunk, Unary or Binary in each receiver mode that all its stages support: shared (call, __call__), exclusive (call_mut) or consuming (call_once). Nothing runs during construction. It is Copyable when every stage is, and copying is explicit.

Parameters

  • reverse (Bool): True for compose, whose stages run right to left.
  • arity (Int): The number of arguments the first stage takes: 0, 1 or 2.
  • *Fs (Movable & Deinitable): The stage types, in the order they were passed.

Implements

Binary, BinaryContract, Copyable, MutableBinary, MutableThunk, MutableUnary, OnceBinary, OnceThunk, OnceUnary, Thunk, ThunkContract, Unary, UnaryContract

Aliases

  • Cells
  • Stage
  • Ordered
  • Plan
  • Arg
  • First
  • Second
  • Out
  • Error

Composition.__call__ { #Composition.call .api-name }

def __call__(self, var arg: Arg) raises Error -> Out

Run the stages on one argument, as call does.

Arguments

  • arg (var Arg): The first stage's argument, consumed.

Returns

Out: The last stage's result.

Raises

Error: The stages' common error; later stages do not run.

2 more overloads

Run the stages, as `call` does, when the first takes no argument.

def __call__(self) raises Error -> Out

Run the stages on two arguments, as `call` does.

def __call__(self, var first: First, var second: Second) raises Error -> Out

Composition.call

def call(self, var arg: Arg) raises Error -> Out

Run the stages on one argument.

Arguments

  • arg (var Arg): The first stage's argument, consumed.

Returns

Out: The last stage's result.

Raises

Error: The stages' common error; later stages do not run.

2 more overloads

Run the stages when the first takes no argument.

def call(self) raises Error -> Out

Run the stages on two arguments.

def call(self, var first: First, var second: Second) raises Error -> Out

Composition.call_mut

def call_mut(mut self, var arg: Arg) raises Error -> Out

Run the stages on one argument with exclusive access to stages that keep state.

Arguments

  • arg (var Arg): The first stage's argument, consumed.

Returns

Out: The last stage's result.

Raises

Error: The stages' common error; later stages do not run.

2 more overloads

Run the stages with exclusive access when the first takes no argument.

def call_mut(mut self) raises Error -> Out

Run the stages on two arguments with exclusive access.

def call_mut(mut self, var first: First, var second: Second) raises Error -> Out

Composition.call_once

def call_once(deinit self, var arg: Arg) raises Error -> Out

Run the stages on one argument once, consuming the composition.

Arguments

  • arg (var Arg): The first stage's argument, consumed.

Returns

Out: The last stage's result.

Raises

Error: The stages' common error; later stages do not run.

2 more overloads

Run the stages once, consuming them, when the first takes no argument.

def call_once(deinit self) raises Error -> Out

Run the stages on two arguments once, consuming the composition.

def call_once(
    deinit self,
    var first: First,
    var second: Second,
) raises Error -> Out

Flipped

Source: fp/functions/flipped.mojo

struct Flipped[F: BinaryContract & Movable & Deinitable](
    Binary where conforms_to(F, Binary),
    MutableBinary where conforms_to(F, Binary) or conforms_to(F, MutableBinary),
    OnceBinary,
    Copyable where conforms_to(F, Copyable),
)

A binary callable called with its two arguments swapped, returned by flip.

It has the receiver modes of the callable it wraps.

Parameters

  • F (BinaryContract & Movable & Deinitable): The wrapped callable's type, a Binary, MutableBinary or OnceBinary.

Implements

Binary, BinaryContract, Copyable, MutableBinary, OnceBinary

Aliases

  • First
  • Second
  • Out
  • Error

Flipped.__call__ { #Flipped.call .api-name }

def __call__(self, var first: First, var second: Second) raises Error -> Out

Call the wrapped callable with the arguments swapped, as call does.

Arguments

  • first (var First): The flipped callable's first argument, passed second.
  • second (var Second): The flipped callable's second argument, passed first.

Returns

Out: The wrapped callable's result.

Raises

Error: The wrapped callable's error, unchanged.

Flipped.call

def call(self, var first: First, var second: Second) raises Error -> Out

Call the wrapped callable with the arguments swapped, reading it.

Arguments

  • first (var First): The flipped callable's first argument, passed second.
  • second (var Second): The flipped callable's second argument, passed first.

Returns

Out: The wrapped callable's result.

Raises

Error: The wrapped callable's error, unchanged.

Flipped.call_mut

def call_mut(mut self, var first: First, var second: Second) raises Error -> Out

Call the wrapped callable with the arguments swapped and exclusive access.

Arguments

  • first (var First): The flipped callable's first argument, passed second.
  • second (var Second): The flipped callable's second argument, passed first.

Returns

Out: The wrapped callable's result.

Raises

Error: The wrapped callable's error, unchanged.

Flipped.call_once

def call_once(
    deinit self,
    var first: First,
    var second: Second,
) raises Error -> Out

Call the wrapped callable once with the arguments swapped, consuming it.

Arguments

  • first (var First): The flipped callable's first argument, passed second.
  • second (var Second): The flipped callable's second argument, passed first.

Returns

Out: The wrapped callable's result.

Raises

Error: The wrapped callable's error, unchanged.

FlippedFunction

Source: fp/functions/flipped.mojo

struct FlippedFunction[R, E, A0, A1, Rs: TypeList[Trait=_Swap, ...]](
    Copyable,
    Binary where Rs.length == 0,
)

A plain function called with its first two arguments swapped, returned by flip.

flip(f)(a, b, rest...) calls f(b, a, rest...); the remaining arguments are borrowed. With no remaining parameters it is also a Binary.

Parameters

  • R (Movable & Deinitable): The function's result type.
  • E (Movable & Deinitable): The function's error type, Never for a pure function.
  • A0 (Movable & Deinitable): The function's first parameter type.
  • A1 (Movable & Deinitable): The function's second parameter type.
  • Rs (TypeList[...]): The types of the remaining parameters.

Implements

Binary, BinaryContract, Copyable

Fields

  • function (def(var a0: A0, var a1: A1, *args: *Rs) raises E thin -> R): The wrapped function.

Aliases

  • First
  • Second
  • Out
  • Error

FlippedFunction.__call__ { #FlippedFunction.call .api-name }

def __call__(self, var first: A1, var second: A0, *rest: *Rs) raises E -> R

Call the function with its first two arguments swapped.

Arguments

  • first (var A1): Passed as the function's second argument.
  • second (var A0): Passed as the function's first argument.
  • *rest (*Rs): The remaining arguments, borrowed and passed in order.

Returns

R: The function's result.

Raises

E: The function's error, unchanged.

FlippedFunction.call

def call(self, var first: First, var second: Second) raises Error -> Out

Binary view: call the function with its two arguments swapped.

Arguments

  • first (var First): The first argument, passed second.
  • second (var Second): The second argument, passed first.

Returns

Out: The function's result.

Raises

Error: The function's error, unchanged.

Identity

Source: fp/functions/composition.mojo

struct Identity[T](Unary, ImplicitlyCopyable)

The unary identity on T, returned by flow[T]() and compose[T]().

Parameters

  • T (Movable & Deinitable): The value type.

Implements

Copyable, ImplicitlyCopyable, Unary, UnaryContract

Aliases

  • Arg
  • Out
  • Error: The error type; Never for a callable that does not raise.

Identity.__call__ { #Identity.call .api-name }

def __call__(self, var arg: T) -> T

Return the argument unchanged, as call does.

Arguments

  • arg (var T): The value, consumed.

Returns

T: arg itself.

Identity.call

def call(self, var arg: Arg) -> Out

Return the argument unchanged.

Arguments

  • arg (var Arg): The value, consumed.

Returns

Out: arg itself.

Partial

Source: fp/functions/partial.mojo

struct Partial[
    R, E, Bs: TypeList[Trait=_Bound, ...], Rs: TypeList[Trait=_Rest, ...],
](
    Copyable,
    Thunk where Rs.length == 0,
    Unary where Rs.length == 1,
    Binary where Rs.length == 2,
)

A plain function with copies of its leading arguments, returned by partial.

Call it with the remaining arguments, which are borrowed. Each call passes the function a fresh copy of every bound argument, so the stored values are never consumed or changed. With 0, 1 or 2 remaining arguments it is also a Thunk, Unary or Binary, which library higher-order functions accept.

Parameters

  • R (Movable & Deinitable): The function's result type.
  • E (Movable & Deinitable): The function's error type, Never for a pure function.
  • Bs (TypeList[...]): The bound argument types.
  • Rs (TypeList[...]): The remaining parameter types.

Implements

Binary, BinaryContract, Copyable, Thunk, ThunkContract, Unary, UnaryContract

Fields

  • function (def(*args: *Rs) raises E thin -> R if (Int(len(values)) == Int(0)) else def(var a0: values[0], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(1)) else def(var a0: values[0], var a1: values[1], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(2)) else def(var a0: values[0], var a1: values[1], var a2: values[2], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(3)) else def(var a0: values[0], var a1: values[1], var a2: values[2], var a3: values[3], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(4)) else def(var a0: values[0], var a1: values[1], var a2: values[2], var a3: values[3], var a4: values[4], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(5)) else def(var a0: values[0], var a1: values[1], var a2: values[2], var a3: values[3], var a4: values[4], var a5: values[5], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(6)) else def(var a0: values[0], var a1: values[1], var a2: values[2], var a3: values[3], var a4: values[4], var a5: values[5], var a6: values[6], *args: *Rs) raises E thin -> R if (Int(len(values)) == Int(7)) else def(var a0: values[0], var a1: values[1], var a2: values[2], var a3: values[3], var a4: values[4], var a5: values[5], var a6: values[6], var a7: values[7], *args: *Rs) raises E thin -> R): The stored function.
  • bound (Tuple[*values]): The bound arguments.

Aliases

  • Arg
  • First
  • Second
  • Out
  • Error

Partial.__call__ { #Partial.call .api-name }

def __call__(self, *rest: *Rs) raises E -> R

Call the function with the bound arguments followed by rest.

Arguments

  • *rest (*Rs): The remaining arguments, borrowed.

Returns

R: The function's result.

Raises

E: The function's error, unchanged.

Partial.call

def call(self, var arg: Arg) raises E -> R

Unary view: call the function when one argument remains.

Arguments

  • arg (var Arg): The remaining argument.

Returns

R: The function's result.

Raises

E: The function's error, unchanged.

2 more overloads

`Thunk` view: call the function when no arguments remain.

def call(self) raises E -> R

`Binary` view: call the function when two arguments remain.

def call(self, var first: First, var second: Second) raises E -> R

Piped

Source: fp/functions/pipeline.mojo

struct Piped[T](Movable)

A value in an eager chained pipeline, started by piped(value).

Each then applies one stage immediately, as pipe(value, f) does, and infers that stage's types from its own call, so a chain has no stage limit and takes plain functions, closures and library Unary values alike. get ends the chain.

Parameters

  • T (Movable & Deinitable): The type of the value the chain holds.

Fields

  • value (T): The value the chain holds.

Piped.get

def get(deinit self) -> T

End the chain and return the value.

Returns

T: The value the chain holds, moved out.

Piped.then

def then[R, //, F: def(var T) -> R](deinit self, function: F) -> Piped[R]

Apply a pure stage and continue the chain with its result.

Parameters

  • R (Movable & Deinitable, inferred): The stage's result type.
  • F (def(var T) -> R): The stage's type: a plain function or a closure.

Arguments

  • function (F): The stage, borrowed; it runs once, now.

Returns

Piped[R]: The chain, holding the stage's result.

def then[R, //, E: AnyType, F: def(var T) raises E -> R](
    deinit self,
    function: F,
) raises E -> Piped[R]

Apply a raising stage; its error stops the chain with its own type.

Limitations

Generic code that forwards a raising callback states its error, then[E=X](f); Mojo 1.1 cannot infer it from a forwarded callback.

Parameters

  • R (Movable & Deinitable, inferred): The stage's result type.
  • E (AnyType): The stage's error type.
  • F (def(var T) raises E -> R): The stage's type: a plain function or a closure that raises E.

Arguments

  • function (F): The stage, borrowed; it runs once, now.

Returns

Piped[R]: The chain, holding the stage's result.

Raises

E: The stage's error, unchanged; later stages do not run.

1 more overload

Apply a library `Unary` value, such as a partial or a composition.

def then[F: Unary](
    deinit self,
    function: F,
) raises F.Error -> Piped[F.Out] where F.Arg == T

Chain ten stages with piped

chained_pipeline.mojo Download
"""An order total in ten stages: plain functions, closures and partials, chained."""
from fp.functions import piped, partial
from std.testing import assert_equal


@fieldwise_init
struct PriceError(Movable, Writable):
    var text: String


def parse_cents(text: String) raises PriceError -> Int:
    try:
        return atol(text)
    except:
        raise PriceError(text)


def multiply(factor: Int, cents: Int) -> Int: return factor * cents
def add(amount: Int, cents: Int) -> Int: return amount + cents
def not_negative(cents: Int) -> Int: return max(cents, 0)
def with_tax(cents: Int) -> Int: return cents + cents * 8 // 100
def to_nickel(cents: Int) -> Int: return (cents + 2) // 5 * 5


def dollars(cents: Int) -> String:
    var rest = cents % 100
    return "$" + String(cents // 100) + (".0" if rest < 10 else ".") + String(rest)


def label(amount: String) -> String: return "total: " + amount


def total(text: String, quantity: Int, percent: Int, shipping: Int) raises PriceError -> String:
    def discount(cents: Int) {imm percent} -> Int:
        return cents - cents * percent // 100
    def ship(cents: Int) {imm shipping} -> Int:
        return cents + shipping
    return (piped(text)
        .then(parse_cents)
        .then(partial(multiply, quantity))
        .then(discount)
        .then(partial(add, -500))
        .then(not_negative)
        .then(ship)
        .then(with_tax)
        .then(to_nickel)
        .then(dollars)
        .then(label)
        .get())


def main() raises:
    var receipt = total("1999", 3, 10, 499)
    assert_equal(receipt, "total: $58.30")
    print(receipt)
    try:
        _ = total("19.99", 3, 10, 499)
    except error:
        print("invalid price:", error.text)

Run from the repository root pixi run mojo run -I src docs/examples/chained_pipeline.mojo

Output

total: $58.30
invalid price: 19.99

total("1999", 3, 10, 499) runs ten then stages: plain functions, two closures that capture percent and shipping, and two partials. The price 1999 cents times 3 is 5997; the 10% discount gives 5398, the -500 coupon 4898, shipping 5397, and 8% tax 5828, which rounds to the nickel as 5830 and prints as total: $58.30. With "19.99", parse_cents raises PriceError, no later stage runs, and the program prints invalid price: 19.99.

Bind leading arguments with partial

partial.mojo Download
"""Bind leading arguments of a native function; bind keywords with a closure."""
from fp.functions import partial


def twice(var x: Int) -> Int:
    return x * 2


def scale(factor: Int, x: Int) -> Int:
    return factor * x


def main() raises:
    var value = 4
    var doubled = partial(twice, value)
    print(doubled())  # 8
    print(doubled())  # 8
    var triple = partial(scale, 3)
    print(triple(5))  # 15

    # Keyword binding is a native closure with a capture list.
    var base = 2
    def basetwo(text: String) raises {base} -> Int:
        return atol(text, base=base)
    print(basetwo("10010"))  # 18

Run from the repository root pixi run mojo run -I src docs/examples/partial.mojo

Output

8
8
15
18

partial(twice, value) copies 4 when it is built and passes a fresh copy on each call, so doubled() returns 8 twice. partial(scale, 3) binds the first argument, and triple(5) returns 15. partial binds only a positional prefix, so the keyword base=2 is bound by the closure basetwo, which returns 18 for "10010".