# Functions

From A Little Lisp for a Small World, the Plazmi Lisp book (https://plazmi.gg/book). Checked against Plazmi Lisp version 2, 12 November 2026. The whole book as one file: https://plazmi.gg/book.md

You have been using words the language gives you: `inc`, `upper`, `count`. A function is a word of your own. This chapter makes them, passes them around, and lets them call themselves.

## fn

`fn` makes a function: a list of names for what it takes, and a form that works out what it gives. Put one first in a list to call it:

```clojure
((fn [n] (* n n)) 7)
```

```text
49
```

That's a function of one value, `n`, giving `n` times `n`, called on 7. More often a function is handed to a word that calls it, as `map` did in the last chapter:

```clojure
(map (fn [n] (* n n)) [1 2 3])
(filter (fn [w] (starts-with? w "@")) ["@mira" "tea" "@cairn"])
```

```text
(1 4 9)
("@mira" "@cairn")
```

A function takes up to six values.

## The short way: #( )

For a small function, `#(…)` is shorter: `%` is the value it takes, or `%1`, `%2` when it takes more than one:

```clojure
(map #(* % %) [1 2 3])
(map #(str %1 " " %2) ["3" "5"] ["roses" "asters"])
```

```text
(1 4 9)
("3 roses" "5 asters")
```

Use `#()` when the whole function fits on a line and is easy to read; `fn` with names when it isn't.

## defn

`defn` gives a function a name, at the top of a plan, for the rest of the plan to use:

```clojure
(defn rings-text [n]
  (if (= n 1) "1 ring" (str n " rings")))
(rings-text 1)
(rings-text 4)
(map rings-text [1 2 3])
```

```text
"1 ring"
"4 rings"
("1 ring" "2 rings" "3 rings")
```

A name given by `defn` lasts for the plan it's in. The next plan starts afresh.

One rule to remember: at the top of a plan, a function you call by name comes from `defn`. A `let` at the top can hold a function and hand it to `map`, but can't call it by name:

```clojure
(let [twice (fn [n] (* 2 n))]
  (twice 21))
```

```text
Step 2, value, op call's fn "twice" isn't a function this plan defined before it, or a name given before it here. Nothing was changed.
```

Write `(defn twice [n] (* 2 n))` instead. Inside a toy it is the other way round: a toy's code has no `defn`, and a `let` inside it holds its functions and calls them by name (chapter 9).

## Functions that make functions

A few words take functions and give new ones. `partial` fills in the first values a function takes; `comp` joins functions into one, the last applied first; `complement` turns a test round; `constantly` always gives one value; `juxt` gives a list of several functions' answers; `fnil` gives a value in place of `nil`:

```clojure
((partial + 10) 5)
((comp upper trim) "  ting  ")
((complement even?) 3)
((constantly "Ting.") "anything")
((juxt count upper) "bell")
((fnil inc 0) nil)
```

```text
15
"TING"
true
"Ting."
[4 "BELL"]
1
```

## A function that calls itself

A function can call itself, on a smaller problem each time, until the problem is small enough to answer straight away:

```clojure
(defn countdown [n]
  (if (= n 0)
    ["off!"]
    (cons n (countdown (dec n)))))
(countdown 3)
```

```text
(3 2 1 "off!")
```

`(countdown 3)` is 3 in front of `(countdown 2)`, which is 2 in front of `(countdown 1)`, and so on down to `(countdown 0)`, which answers without calling itself. Every such function needs a case like that, or it never ends. One that never ends is stopped, and nothing it did is kept:

```clojure
(defn forever [n] (forever (inc n)))
(forever 0)
```

```text
That recursed too deeply. Nothing was changed.
```

## loop and recur

`loop` is a function and its first call in one. It names values, like a `let`, and `recur` starts it again with new ones. This adds up 1 to 10:

```clojure
(loop [n 1
       total 0]
  (if (> n 10)
    total
    (recur (inc n) (+ total n))))
```

```text
55
```

A `loop` can go round many more times than a function can call itself, because `recur` doesn't build up a chain of calls. Every round is a step of the plan's fuel, though, so a loop with no way out is stopped in the end (chapter 17).

Most of the time you won't need either: `map`, `filter` and `reduce` say what you mean more plainly. Reach for `loop` when each round depends on the last in a way they don't fit.

## A function as a value

A function is a value like any other: it can be named, put in a list or a map, and handed on. This keeps a small table of greetings by the time of day:

```clojure
(let [greetings {:dawn (fn [who] (str "Early, " who "!"))
                 :night (fn [who] (str "Hush, " who "."))}
      greet (get greetings :night)]
  (map greet ["Mira" "Cairn"]))
```

```text
("Hush, Mira." "Hush, Cairn.")
```

## Try it

1. Write `(defn shout [t] …)` that answers `t` in capitals with `"!"` after it, and use it on `"ting"`.
2. With `#()`, answer each number of `[1 2 3]` plus 100.
3. Write `(defn sum-list [l] …)` that adds up a list by calling itself on its `rest`. Then do the same with `reduce`.
4. With `loop`, answer the first power of 2 over 1,000.

## Recap

- `(fn [a b] …)` makes a function; `#(… % …)` is the short form; up to six values.
- `defn` names a function at the top of a plan; a top-level `let` can hold one but not call it by name.
- `partial`, `comp`, `complement`, `constantly`, `juxt` and `fnil` make functions from functions.
- A function can call itself; `loop` and `recur` go round without building up calls. Both stop at the fuel.

Next: chance, and why Plazmi's always repeats.


---

Before: [Working over lists](https://plazmi.gg/book/over-lists.md). Next: [Chance that repeats](https://plazmi.gg/book/chance.md). Contents: https://plazmi.gg/book.md
