---
title: "Standard Library: Higher-Order Functions"
output: arl::arl_html_vignette
pkgdown:
  as_is: true
vignette: >
  %\VignetteIndexEntry{Standard Library: Higher-Order Functions}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

<!-- AUTO-GENERATED from inst/arl/ source files. Do not edit manually. -->
<!-- Regenerate with: make lang-docs -->

```{r setup, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
arl::register_knitr_engine()
```

*Examples on this page may reference functions from other stdlib modules
without showing explicit `(import ...)` statements. In the REPL or your
own code, you will need to import non-prelude modules before using their
exports — see [Importing modules](lang-reference.html#importing-modules).*


## Core Higher-Order Functions {#section-core-higher-order-functions}

The fundamental building blocks for functional programming in Arl.
These functions operate on lists and follow the convention of taking
the function argument first, then the data argument.

### map {#map}

Apply function to each element. With one list, maps fn over it.
With multiple lists, maps fn over corresponding elements (like Scheme's map).

**Signature:** `(map fn lst rest...)`

**Parameters:**
- **`fn`** — Function to apply to each element (or corresponding elements)
- **`lst`** — First list to transform
- **`rest`** — Additional lists for multi-list mapping

**Examples:**
```{arl}
(map (lambda (x) (* x 2)) (list 1 2 3))  ; => (2 4 6)
(map + (list 1 2 3) (list 4 5 6))         ; => (5 7 9)
```

```{arl, include=FALSE}
(assert-equal (list 2 4 6) (map (lambda (x) (* x 2)) (list 1 2 3)))
(assert-equal (list 5 7 9) (map + (list 1 2 3) (list 4 5 6)))
```

**See also:** [filter](#filter), [mapcat](#mapcat), [reduce](#reduce)

---

### mapcat {#mapcat}

Map then concatenate results. Uses do.call(c, ...) for O(n) concatenation.

**Signature:** `(mapcat fn lst)`

**Parameters:**
- **`fn`** — Function that returns a list for each element
- **`lst`** — List to transform

**Examples:**
```{arl}
(mapcat (lambda (x) (list x (* x 10))) (list 1 2 3))  ; => (1 10 2 20 3 30)
(mapcat (lambda (x) (list x x)) (list 1 2 3))          ; => (1 1 2 2 3 3)
```

```{arl, include=FALSE}
(assert-equal (list 1 10 2 20 3 30) (mapcat (lambda (x) (list x (* x 10))) (list 1 2 3)))
```

**See also:** [map](#map), [flatten](lang-list-seq.html#flatten)

---

### filter {#filter}

Filter items by predicate.

**Signature:** `(filter pred lst)`

**Parameters:**
- **`pred`** — Predicate function; elements where it returns #t are kept
- **`lst`** — List to filter

**Examples:**
```{arl}
(filter (lambda (x) (> x 2)) (list 1 2 3 4 5))  ; => (3 4 5)
(filter even? (list 1 2 3 4 5 6))                 ; => (2 4 6)
(filter string? (list 1 "a" 2 "b"))               ; => ("a" "b")
```

```{arl, include=FALSE}
(assert-equal (list 3 4 5) (filter (lambda (x) (> x 2)) (list 1 2 3 4 5)))
```

**See also:** [remove](#remove), [take-while](lang-list-seq.html#take-while), [drop-while](lang-list-seq.html#drop-while)

---

### remove {#remove}

Remove items where predicate is true.

**Signature:** `(remove pred lst)`

**Parameters:**
- **`pred`** — Predicate function; elements where it returns #t are removed
- **`lst`** — List to filter

**Examples:**
```{arl}
(remove even? (list 1 2 3 4 5 6))                 ; => (1 3 5)
(remove (lambda (x) (> x 3)) (list 1 2 3 4 5))   ; => (1 2 3)
```

```{arl, include=FALSE}
(assert-equal (list 1 3 5) (remove even? (list 1 2 3 4 5 6)))
```

**See also:** [filter](#filter)

---

### reduce {#reduce}

Reduce list with function.

**Signature:** `(reduce fn lst rest...)`

**Parameters:**
- **`fn`** — Binary function taking accumulator and current element
- **`lst`** — List to reduce
- **`rest`** — Optional initial accumulator value

**Examples:**
```{arl}
(reduce + (list 1 2 3 4))       ; => 10
(reduce * (list 1 2 3 4))       ; => 24
(reduce + (list 1 2 3) 100)     ; => 106 (with initial value)
(reduce string-append (list "a" "b" "c"))  ; => "abc"
```

```{arl, include=FALSE}
(assert-equal 10 (reduce + (list 1 2 3 4)))
(assert-equal 24 (reduce * (list 1 2 3 4)))
(assert-equal 106 (reduce + (list 1 2 3) 100))
```

**See also:** [foldl](#foldl), [foldr](#foldr), [map](#map)

---

### foldl {#foldl}

Left fold alias for reduce. Applies fn as (fn acc elem).

**Signature:** `(foldl fn lst rest...)`

**Parameters:**
- **`fn`** — Binary function taking accumulator and current element
- **`lst`** — List to fold over
- **`rest`** — Optional initial accumulator value

**Examples:**
```{arl}
(foldl + (list 1 2 3 4))        ; => 10
(foldl - (list 1 2 3) 10)       ; => 4 (10 - 1 - 2 - 3)
(foldl (lambda (acc x) (cons x acc)) (list 1 2 3) (list))  ; => (3 2 1)
```

```{arl, include=FALSE}
(assert-equal 10 (foldl + (list 1 2 3 4)))
(assert-equal 4 (foldl - (list 1 2 3) 10))
(assert-equal (list 3 2 1) (foldl (lambda (acc x) (cons x acc)) (list 1 2 3) (list)))
```

**See also:** [foldr](#foldr), [reduce](#reduce)

---

### foldr {#foldr}

Right fold. Applies fn as (fn elem acc).

**Signature:** `(foldr fn lst rest...)`

**Parameters:**
- **`fn`** — Binary function taking current element and accumulator
- **`lst`** — List to fold over from the right
- **`rest`** — Optional initial accumulator value

**Examples:**
```{arl}
(foldr + (list 1 2 3 4))        ; => 10
(foldr - (list 1 2 3) 10)       ; => -8 (1 - (2 - (3 - 10)))
(foldr cons (list 1 2 3) (list)) ; => (1 2 3) (preserves order)
```

```{arl, include=FALSE}
(assert-equal 10 (foldr + (list 1 2 3 4)))
(assert-equal -8 (foldr - (list 1 2 3) 10))
(assert-equal (list 1 2 3) (foldr cons (list 1 2 3) (list)))
```

**See also:** [foldl](#foldl), [reduce](#reduce)

---

### every? {#every-p}

Return #t if predicate true for all items.

**Signature:** `(every? pred lst)`

**Parameters:**
- **`pred`** — Predicate function to test each element
- **`lst`** — List to check

**Examples:**
```{arl}
(every? positive? (list 1 2 3))       ; => #t
(every? even? (list 2 4 6))           ; => #t
(every? even? (list 2 3 6))           ; => #f
(every? string? (list "a" "b" "c"))   ; => #t
```

```{arl, include=FALSE}
(assert-true (every? positive? (list 1 2 3)))
(assert-false (every? even? (list 2 3 6)))
```

**See also:** [any?](#any-p), [filter](#filter)

---

### any? {#any-p}

Return #t if predicate true for any item.

**Signature:** `(any? pred lst)`

**Parameters:**
- **`pred`** — Predicate function to test each element
- **`lst`** — List to check

**Examples:**
```{arl}
(any? even? (list 1 3 4 5))           ; => #t
(any? negative? (list 1 2 3))         ; => #f
(any? string? (list 1 "a" 2))         ; => #t
```

```{arl, include=FALSE}
(assert-true (any? even? (list 1 3 4 5)))
(assert-false (any? negative? (list 1 2 3)))
```

**See also:** [every?](#every-p), [filter](#filter)

---

### complement {#complement}

Negate predicate.

**Signature:** `(complement pred)`

**Parameters:**
- **`pred`** — Predicate function to negate

**Examples:**
```{arl}
(define not-even? (complement even?))
(not-even? 3)                          ; => #t
(not-even? 4)                          ; => #f
(filter (complement null?) (list 1 #nil 2 #nil 3))  ; => (1 2 3)
```

```{arl, include=FALSE}
(assert-true ((complement even?) 3))
(assert-false ((complement even?) 4))
```

**See also:** [not](lang-core.html#not), [filter](#filter)

---

### compose {#compose}

Compose two functions.

**Signature:** `(compose f g)`

**Parameters:**
- **`f`** — Outer function (applied second)
- **`g`** — Inner function (applied first)

**Examples:**
```{arl}
(define add1-then-double (compose (lambda (x) (* x 2)) (lambda (x) (+ x 1))))
(add1-then-double 3)                   ; => 8  ((3+1)*2)
(define abs-sum (compose abs +))
(abs-sum -3 -4)                        ; => 7
```

```{arl, include=FALSE}
(assert-equal 8 ((compose (lambda (x) (* x 2)) (lambda (x) (+ x 1))) 3))
```

**See also:** [partial](#partial)

---

### partial {#partial}

Partially apply function.

**Signature:** `(partial fn captured...)`

**Parameters:**
- **`fn`** — Function to partially apply
- **`captured`** — Arguments to bind to fn's first positions

**Examples:**
```{arl}
(define add5 (partial + 5))
(add5 3)                               ; => 8
(define greet (partial string-append "Hello, "))
(greet "world")                        ; => "Hello, world"
```

```{arl, include=FALSE}
(assert-equal 8 ((partial + 5) 3))
```

**See also:** [compose](#compose)

---

## Advanced Functional Programming {#section-advanced-functional-programming}

Higher-order combinators for advanced functional patterns including
currying, juxtaposition, memoization, and iteration.

### curry {#curry}

Curry a function - enables partial application
with optional initial arguments.

**Signature:** `(curry fn initial-args...)`

**Parameters:**
- **`fn`** — Function to curry (must have fixed arity)
- **`initial-args`** — Optional arguments to apply immediately

**Examples:**
```{arl}
(define add (curry (lambda (a b) (+ a b))))
(define add5 (add 5))
(add5 3)                               ; => 8
(define multiply (curry (lambda (a b) (* a b))))
((multiply 3) 4)                       ; => 12
```

```{arl, include=FALSE}
(assert-equal 8 ((curry (lambda (a b) (+ a b)) 5) 3))
```

**See also:** [partial](#partial)

---

### juxt {#juxt}

Juxtaposition - apply multiple functions to same args, return list of results.

**Signature:** `(juxt fns...)`

**Parameters:**
- **`fns`** — Functions to apply to the arguments

**Examples:**
```{arl}
(define stats (juxt min max mean))
(stats (c 1 2 3 4 5))                  ; => (1 5 3)
(define first-and-last (juxt car last))
(first-and-last (list 1 2 3))          ; => (1 3)
```

```{arl, include=FALSE}
(assert-equal (list 1 5 3) ((juxt min max mean) (c 1 2 3 4 5)))
(assert-equal (list 1 3) ((juxt car last) (list 1 2 3)))
```

**See also:** [map](#map), [compose](#compose)

---

### constantly {#constantly}

Return a function that always returns the given value.

**Signature:** `(constantly value)`

**Parameters:**
- **`value`** — Value to return regardless of arguments

**Examples:**
```{arl}
(define always-42 (constantly 42))
(always-42)                             ; => 42
(always-42 "ignored" "args")            ; => 42
(map (constantly 0) (list 1 2 3))       ; => (0 0 0)
```

```{arl, include=FALSE}
(assert-equal 42 ((constantly 42)))
(assert-equal (list 0 0 0) (map (constantly 0) (list 1 2 3)))
```

---

### iterate {#iterate}

Apply function n times to initial value.

**Signature:** `(iterate fn n init)`

**Parameters:**
- **`fn`** — Unary function to apply repeatedly
- **`n`** — Number of times to apply fn
- **`init`** — Starting value

**Examples:**
```{arl}
(iterate (lambda (x) (* x 2)) 5 1)     ; => 32  (1 -> 2 -> 4 -> 8 -> 16 -> 32)
(iterate inc 3 0)                       ; => 3   (0 -> 1 -> 2 -> 3)
(iterate (lambda (x) (* x x)) 2 2)     ; => 16  (2 -> 4 -> 16)
```

```{arl, include=FALSE}
(assert-equal 32 (iterate (lambda (x) (* x 2)) 5 1))
(assert-equal 3 (iterate inc 3 0))
(assert-equal 16 (iterate (lambda (x) (* x x)) 2 2))
```

**See also:** [iterate-until](#iterate-until), [reduce](#reduce)

---

### iterate-until {#iterate-until}

Apply function starting from init, collecting
values until predicate becomes true. Includes all values where
predicate is false, stops when next value would satisfy predicate.

**Signature:** `(iterate-until fn init pred)`

**Parameters:**
- **`fn`** — Unary function to apply repeatedly
- **`init`** — Starting value
- **`pred`** — Predicate that signals when to stop collecting

**Examples:**
```{arl}
(iterate-until (lambda (x) (* x 2)) 1 (lambda (x) (> x 100)))
  ; => (1 2 4 8 16 32 64)  (stops before 128 which exceeds 100)
(iterate-until inc 0 (lambda (x) (>= x 5)))
  ; => (0 1 2 3 4)
```

```{arl, include=FALSE}
(assert-equal (list 1 2 4 8 16 32 64) (iterate-until (lambda (x) (* x 2)) 1 (lambda (x) (> x 100))))
(assert-equal (list 0 1 2 3 4) (iterate-until inc 0 (lambda (x) (>= x 5))))
```

**See also:** [iterate](#iterate), [take-while](lang-list-seq.html#take-while)

---

### memoize {#memoize}

Memoize function - cache results for previously seen arguments.

**Signature:** `(memoize fn)`

**Parameters:**
- **`fn`** — Function whose results to cache by arguments

**Examples:**
```{arl}
(define slow-fib (lambda (n) (if (< n 2) n (+ (slow-fib (- n 1)) (slow-fib (- n 2))))))
(define fast-fib (memoize slow-fib))
(fast-fib 10)                          ; => 55
(fast-fib 10)                          ; => 55 (cached, instant)
```

```{arl, include=FALSE}
(assert-equal 4 ((memoize (lambda (x) (* x x))) 2))
(assert-equal 4 ((memoize (lambda (x) (* x x))) 2))
```

---

## Iteration and Counting {#section-iteration-and-counting}

Functions for side-effecting iteration and counting over sequences.

### for-each {#for-each}

Apply function to each element for side effects.
Returns #nil. Supports multiple lists like multi-list map.

**Signature:** `(for-each fn lst rest...)`

**Parameters:**
- **`fn`** — Function to apply for side effects
- **`lst`** — First list
- **`rest`** — Additional lists for multi-list iteration

**Examples:**
```{arl}
(for-each print '(1 2 3))  ; prints 1 2 3, returns #nil
```

```{arl, include=FALSE}
(assert-equal #nil (for-each (lambda (x) x) (list 1 2 3)))
```

**See also:** [map](#map)

---

### count {#count}

Count elements matching predicate.

**Signature:** `(count pred lst)`

**Parameters:**
- **`pred`** — Predicate function to test each element
- **`lst`** — List to count matching elements in

**Examples:**
```{arl}
(count even? (list 1 2 3 4))  ; => 2
(count even? (list))           ; => 0
```

```{arl, include=FALSE}
(assert-equal 2 (count even? (list 1 2 3 4)))
(assert-equal 0 (count even? (list)))
```

**See also:** [filter](#filter), [every?](#every-p), [any?](#any-p)

---

### map-indexed {#map-indexed}

Map with index. Calls (fn index element) for each element,
with 0-based indices.

**Signature:** `(map-indexed fn lst)`

**Parameters:**
- **`fn`** — Function taking index and element
- **`lst`** — List to map over

**Examples:**
```{arl}
(map-indexed list '(a b c))  ; => ((0 a) (1 b) (2 c))
```

```{arl, include=FALSE}
(assert-equal (list (list 0 'a) (list 1 'b) (list 2 'c)) (map-indexed list (list 'a 'b 'c)))
```

**See also:** [map](#map)

---

### group-by {#group-by}

Group elements by key function. Returns a dict mapping
each key (as string) to a list of matching elements.

**Signature:** `(group-by key-fn lst)`

**Parameters:**
- **`key-fn`** — Function to compute the grouping key for each element
- **`lst`** — List to group

**Examples:**
```{arl}
(group-by even? '(1 2 3 4))  ; => dict with TRUE->(2 4), FALSE->(1 3)
```

**See also:** [frequencies](#frequencies), [filter](#filter)

---

### frequencies {#frequencies}

Count occurrences of each element. Returns a dict mapping
each element (as string) to its count.

**Signature:** `(frequencies lst)`

**Parameters:**
- **`lst`** — List to count element frequencies in

**Examples:**
```{arl}
(frequencies '(a b a c b a))  ; => dict with a->3 b->2 c->1
```

**See also:** [group-by](#group-by), [count](#count)

---

## Logical Operations {#section-logical-operations}

Core logical operations for Arl. Note that `and` and `or` are compiler
special forms (not functions) with short-circuit evaluation, so they
are not part of this module.

### not {#not}

Logical negation with Arl truthiness.

**Signature:** `(not x)`

**Parameters:**
- **`x`** — Value to negate

**Examples:**
```{arl}
(not #t)          ; => #f
(not #f)          ; => #t
(not 0)           ; => #t (0 is falsy)
(not 1)           ; => #f (non-zero is truthy)
(not #nil)        ; => #t (NULL is falsy)
(not "hello")     ; => #f (non-empty values are truthy)
```

```{arl, include=FALSE}
(assert-false (not #t))
(assert-true (not #f))
(assert-true (not 0))
(assert-false (not 1))
(assert-true (not #nil))
(assert-false (not "hello"))
```

**Note:** Arl follows Scheme-like truthiness: #f/FALSE, #nil/NULL, and 0 are falsy. Everything else is truthy. This differs from R where only FALSE and NULL are falsy.

**See also:** [xor](#xor), [and](lang-core.html#and), [or](lang-core.html#or) (special forms)

---

### xor {#xor}

Logical exclusive OR with Arl truthiness.

**Signature:** `(xor a b)`

**Parameters:**
- **`a`** — First value
- **`b`** — Second value

**Examples:**
```{arl}
(xor #t #f)       ; => #t
(xor #f #t)       ; => #t
(xor #t #t)       ; => #f
(xor #f #f)       ; => #f
(xor 1 0)         ; => #t (1 is truthy, 0 is falsy)
(xor 1 2)         ; => #f (both truthy)
```

```{arl, include=FALSE}
(assert-true (xor #t #f))
(assert-true (xor #f #t))
(assert-false (xor #t #t))
(assert-false (xor #f #f))
(assert-true (xor 1 0))
(assert-false (xor 1 2))
```

**Note:** Exclusive OR: returns #t when exactly one argument is truthy, #f when both are truthy or both are falsy.

**See also:** [not](lang-core.html#not), [and](lang-core.html#and), [or](lang-core.html#or) (special forms)

---

