Part I. The language · this page as markdown

Names

A value is more useful once it has a name. This chapter gives values names with let, takes maps and lists apart into names, and ends with the one kind of name that can change.

let #

let takes a list of names and values, in pairs, and then the forms that use them:

#names-let
(let [rings 3]
  (* rings 2))
It answers
6

Inside the let, rings stands for 3. The let answers what its last form answers.

A let can give several names. Each can use the ones before it:

#names-several
(let [legs 4
      stools 3
      all-legs (* legs stools)]
  (str stools " stools, " all-legs " legs"))
It answers
"3 stools, 12 legs"

Where a name reaches #

A name reaches only the forms inside its let. Outside, it means nothing, and a plan that uses it there is refused before it runs:

Refused#names-outside
(let [rings 3] rings)
rings
It answers
That plan writes rings in a form Plazmi Lisp doesn't take, so nothing in it ran. Nothing was changed.

The first form was fine on its own; the second used rings where no let gave it. Since the plan is checked whole before anything runs, the first form didn't run either.

Good names #

A name you give starts with a small letter and goes on with small letters, digits, - or _, up to 32 characters, and may end in ? or !: rings, guest-list, open?. Use names that say what the value is.

Give names of your own, not words the language already has. count, text, name and colour are all words of the language, and a plan that tries to give one as a name can be refused:

Refused#names-taken
(let [colour (atom "rose")]
  (deref colour))
It answers
That plan writes let in a form Plazmi Lisp doesn't take, so nothing in it ran. Nothing was changed.

Call it shade or door-colour instead, and it runs. (What atom and deref do comes at the end of this chapter.)

Values don't change #

A name stands for its value, and the value stays as it is. assoc gives a map with one key set, and leaves the map it was given alone:

#names-unchanged
(let [bell {:rings 0}
      rung (assoc bell :rings 1)]
  [bell rung])
It answers
[{:rings 0} {:rings 1}]

bell is still {:rings 0}. This is true of every value in the language: a list, a map or a text is never changed in place, and a word that seems to change one (assoc, conj, update) answers a new one. It makes programs easy to read: a name means the same thing all the way down.

A let can give a name again, further down its list, and the later one is used from there on:

#names-again
(let [n 1
      n (+ n 1)]
  n)
It answers
2

Taking values apart #

Often a value is a list or a map, and you want names for its parts. Write the names in the shape of the value:

#names-apart
(let [[first-guest second-guest] ["@mira" "@cairn" "@wisp"]]
  (str first-guest " and " second-guest))
(let [{:keys [rings colour]} {:rings 4 :colour "rose"}]
  (str "A " colour " bell, rung " rings " times"))
It answers
"@mira and @cairn"
"A rose bell, rung 4 times"

[first-guest second-guest] names the first two items of the list. {:keys [rings colour]} names the values of the keys :rings and :colour. A key the map hasn't got gives nil.

Reading a key #

You don't always need a let to read a map. A keyword is also a word that reads its own key, and get reads any key, with a value to use when it's missing:

#names-keys
(:rings {:rings 4})
(get {:rings 4} :rings)
(get {:rings 4} :chimes 0)
It answers
4
4
0

A name that changes, at the top of a plan #

At the top of a plan (not inside a toy), a name can hold a value that changes as the plan runs. (atom v) makes such a name, deref reads it, reset! gives it a new value, and swap! changes it with a word:

#names-atom
(let [total (atom 0)]
  (dotimes [i 4]
    (swap! total + i))
  (deref total))
It answers
6

(dotimes [i 4] …) runs its forms four times, with i as 0, 1, 2 and 3 (chapter 4 has more). Each time, (swap! total + i) adds i to the total. swap! takes these shapes:

#names-swaps
(let [guests (atom [])
      lit (atom false)
      shade (atom "rose")
      counts (atom {:rings 0})]
  (swap! guests conj "@mira")
  (swap! guests conj "@cairn")
  (swap! lit not)
  (reset! shade "sage")
  (swap! counts update :rings + 5)
  (swap! counts assoc :chimes 2)
  [(deref guests) (deref lit) (deref shade) (deref counts)])
It answers
[["@mira" "@cairn"] true "sage" {:rings 5, :chimes 2}]

(swap! x + n) and (swap! x - n) add and take away, (swap! x not) turns true and false over, (swap! x conj v) adds to the end of a list, (swap! x assoc :k v) sets a key, and (swap! x update :k + n) adds to one key. These are the shapes the table lists. Inside a toy there are no atoms: a toy keeps what changes in its state (chapter 9).

Try it #

  1. Use let to name the width and depth of a room, 4 and 3, and answer its area.
  2. Take apart {:name "Bell" :rings 7} with {:keys […]} and answer "Bell: 7".
  3. Why is (let [count 3] count) a poor plan, even where it runs? What would you call it instead?
  4. With an atom, add up the numbers 0 to 9 and answer the total.

Recap #

Next: text, lists and maps, and the words that work with them.

Written by Claude, Plazmi's writer, for Plazmi, a service of Manatee Media LLC. Text © 2026 Manatee Media LLC. The examples are free to copy, change and run.