Skip to main content

Special Operators

NumFu includes several expressive operators to make functional programming more intuitive:

  • >> for function composition
  • |> for data piping
  • ... for list spreading and rest arguments

Function Composition (>>)​

Function composition lets you build new functions by chaining simpler ones together.

let add1 = {x -> x + 1} in
let double = {x -> x * 2} in
let add1ThenDouble = add1 >> double in
add1ThenDouble(5) // 12 ((5 + 1) * 2)

You can chain as many functions as needed:

import * from "std"

let capitalize = {s -> toUpperCase(s[0]) + slice(s, 1, -1)} in
let clean = trim >> toLowerCase >> capitalize in
clean(" HELLO WORLD ") // "Hello World"

Piping (|>)​

Piping is about applying a series of functions to a value. It passes the result of one expression as argument to the next function:

5 |> {x -> x + 1} |> {x -> x * 2}   // 12

This is equivalent to:

{ x -> x * 2 }({ x -> x + 1 }(5))

Piping makes data processing chains more readable and expressive

import format from "std"

let isEven = {x -> x % 2 == 0} in
let double = {x -> x * 2} in
let halve = {x -> x / 2} in
6 |> {x -> if isEven(x) then double(x) else halve(x)}
|> {x -> format("Result: {}", x)}
Result: 12

Composition vs Piping​

Function Composition (>>) creates a new function:

let f = {x -> x + 1} >> {x -> x * 2} in
f(5) // 12

Piping (|>) applies functions immediately:

5 |> {x -> x + 1} |> {x -> x * 2}    // 12

Currying + Composition​

Currying lets you fix arguments before composing:

let add = {x, y -> x + y} in
let multiply = {x, y -> x * y} in

let pipeline = add(10) >> multiply(2) in
pipeline(5) // 30 ((5 + 10) * 2)

Spread Operator (...)​

The spread operator unpacks list elements or collects extra arguments.

List Spreading​

Use ... inside lists to insert the contents of other lists:

[1, ...[2, 3], 4];            // [1, 2, 3, 4]
[...[1, 2], ...[3, 4]]; // [1, 2, 3, 4]

Spreading is especially useful when combining multiple variables:

let a = [1, 2], b = [3, 4], c = [5, 6] in
[0, ...a, ...b, ...c, 7] // [0, 1, 2, 3, 4, 5, 6, 7]

Empty lists are ignored when spread:

[1, ...[], 2];                // [1, 2]
[...[], ...[]]; // []

Spread in Function Calls and Parameters​

... can be used to collect or expand arguments in functions.

For collecting arguments, see here.

As within lists, you can use the spread operator inside function calls to expand arguments:

import log from "math"

let args = [64, 2] in
log(...args) // same as log(64, 2) -> 6