Functions
Defining Functions
Section titled “Defining Functions”Use fn to declare a function with named parameters:
fn greet(name) { echo "hello, $name"}
greet("world") # hello, worldThe return value is the last expression evaluated in the body:
fn double(x) { x * 2}
let result = double(5) # 10Multiple Parameters
Section titled “Multiple Parameters”Separate parameters with commas:
fn add(a, b) { a + b}
let sum = add(3, 4) # 7fn clamp(value, lo, hi) { if value < lo { lo } else if value > hi { hi } else { value }}
let clamped = clamp(150, 0, 100) # 100Functions Are Immutable Bindings
Section titled “Functions Are Immutable Bindings”Functions are declared with let semantics. They live in the command namespace, separate from the variable namespace. You cannot reassign a function name.
Closures
Section titled “Closures”Lambdas capture their declaration scope:
fn make_multiplier(factor) { x => x * factor}
let triple = make_multiplier(3)[1, 2, 3, 4].map(triple) # [3, 6, 9, 12]Using Functions with Chains
Section titled “Using Functions with Chains”Functions integrate naturally with map, filter, and other chain methods:
fn is_source_file(name) { name.endsWith(".d") || name.endsWith(".di")}
fn format_entry(path) { " -> $path"}
`ls -R src/`.filter(x => is_source_file(x)).map(x => format_entry(x))With reduce:
fn running_total(acc, x) { acc + x.toNumber()}
let total = `cat amounts.txt`.reduce(0, (acc, x) => running_total(acc, x))(total)Practical Example
Section titled “Practical Example”A script that processes server logs and summarizes status codes:
fn extract_status(line) { line.split(" ")[8]}
fn is_error(status) { status.startsWith("5") || status.startsWith("4")}
let errors = `cat access.log` .map(x => extract_status(x)) .filter(x => is_error(x)) .wordcount() .take(10)
for entry in errors { echo "status $(entry["word"]): $(entry["count"]) occurrences"}Recursion
Section titled “Recursion”Functions can call themselves:
fn factorial(n) { if n <= 1 { 1 } else { n * factorial(n - 1) }}
let result = factorial(6) # 720(result)Be mindful of lash’s loop protection — recursive calls are not subject to the loop iteration limit, but deep recursion may exhaust the call stack.