← All Examples FP
Pipes & Composition
JAPL's pipe-forward operator |> lets data flow left-to-right through function chains. Combined with higher-order functions, this enables expressive, readable data transformations.
Source Code: Pipes
fn double(x: Int) -> Int { x * 2 }
fn add(x: Int, y: Int) -> Int { x + y }
fn to_str(x: Int) -> String { show(x) }
fn main() {
let result = 5 |> double |> double
println(show(result))
let msg = 42 |> to_str
println(msg)
} Source Code: Higher-Order Functions
fn apply(f: fn(Int) -> Int, x: Int) -> Int { f(x) }
fn double(x: Int) -> Int { x * 2 }
fn square(x: Int) -> Int { x * x }
fn apply_twice(f: fn(Int) -> Int, x: Int) -> Int { f(f(x)) }
fn main() {
println(show(apply(double, 5)))
println(show(apply(square, 4)))
println(show(apply_twice(double, 3)))
let add_ten = fn(x: Int) { x + 10 }
println(show(apply(add_ten, 5)))
} What This Demonstrates
- Pipe-forward operator
|>-- Passes the left-hand value as the first argument to the right-hand function.5 |> doubleis equivalent todouble(5). - Chained pipes -- Multiple pipes compose left-to-right:
5 |> double |> doublecomputesdouble(double(5))=20. - Functions as values -- Functions can be passed as arguments.
apply(double, 5)callsdoublewith5. - Function types --
fn(Int) -> Intis the type of a function taking anIntand returning anInt. - Anonymous functions --
fn(x: Int) { x + 10 }creates an inline function (lambda) without naming it. - Applying functions multiple times --
apply_twicedemonstrates that higher-order functions can express powerful abstractions concisely.
Line-by-Line Breakdown
let result = 5 |> double |> double- Starts with
5, pipes it intodouble(getting10), then pipes that intodoubleagain (getting20). Reads left-to-right, like a Unix pipeline. fn apply(f: fn(Int) -> Int, x: Int) -> Int- Takes a function
fand a valuex, and appliesftox. The function type is writtenfn(Int) -> Int. fn apply_twice(f: fn(Int) -> Int, x: Int) -> Int { f(f(x)) }- Applies
ftwice.apply_twice(double, 3)computesdouble(double(3))=12. let add_ten = fn(x: Int) { x + 10 }- An anonymous function bound to a local variable. It can be passed to
applyjust like a named function.
Try Modifying
- Build a longer pipeline:
5 |> double |> square |> to_strand print the result. - Write a
composefunction that takes two functions and returns their composition. - Create a
mapfunction that applies a function to each element of a list. - Use anonymous functions directly in a pipe:
5 |> fn(x: Int) { x * 3 }.