Part II. Making things · this page as markdown

A first toy

A toy is a thing at your home that visitors can play. It has a name, words it answers to, and a little memory of its own. This chapter makes one, a bell that counts its rings, and then makes it better.

The bell #

#bell
(defobject bell
  {:name "Bell"
   :state {:rings 0}
   :verbs {:ring (fn [self who]
                   (put! self :rings (inc (:rings self)))
                   (say self (str "Ting. That's " (:rings self) " rings.")))}})
It answers
The bell is ready.

Mira comes over and rings it:

Played
> ring bell
[Juniper's bell] Ting. That's 1 rings.
> ring bell
[Juniper's bell] Ting. That's 2 rings.

Here is what each part does.

Through a chat app, a new toy stands somewhere free in the garden. With a key, a new toy waits until you stand it somewhere with place (chapter 15).

Reading and keeping #

put! keeps a value straight away, so the read after it sees the new one: that's why the bell's first line says 1, not 0. (state self) is the whole state, and (get self :rings) is the same as (:rings self).

Nothing in a verb is kept until the verb finishes. If it stops partway, by a mistake or a refusal (chapter 13), its put!s are forgotten, as a plan's changes are.

Better words #

"1 rings" isn't right. A function inside the verb can choose the word. A toy has no defn, so name the function with let:

#bell-better
(defobject bell
  {:name "Bell"
   :state {:rings 0}
   :verbs {:ring (fn [self who]
                   (let [n (inc (:rings self))
                         times (fn [k] (if (= k 1) "once" (str k " times")))]
                     (put! self :rings n)
                     (say self (str "Ting. Rung " (times n) "."))))}})
It answers
The bell is ready.
Played
> ring bell
[Juniper's bell] Ting. Rung 3 times.

Two things happened. The bell was made again, with the same name, so it is the same bell where it stood, with its new code and its old state: it remembered its 2 rings. And the new word is right.

Making a toy again is how you change one. Its state stays unless you change it; chapter 18 has advice on state that lasts.

Who played #

who is who played. To the toy's code, a neighbour is their handle, like "@mira"; its maker is always "@you"; a person visiting is their name. When the toy says a handle aloud, it reads as the resident's name:

#bell-who
(defobject bell
  {:name "Bell"
   :state {:rings 0}
   :verbs {:ring (fn [self who]
                   (let [n (inc (:rings self))]
                     (put! self :rings n)
                     (say self (str "Ting. Thank you, " who "."))))}})
It answers
The bell is ready.
Played
> ring bell
[Juniper's bell] Ting. Thank you, Mira.

And when Juniper rings it herself, who is "@you", and the reply says so:

Played
> ring bell
[Your bell] Ting. Thank you, you.

That line reads badly, which is the point: a toy that speaks to who should check for "@you". Chapter 10 does.

More than one verb #

A toy answers to as many verbs as its map has, up to 24. A second verb on the bell lets a visitor read the count without ringing:

#bell-two-verbs
(defobject bell
  {:name "Bell"
   :state {:rings 0}
   :verbs {:ring (fn [self who]
                   (put! self :rings (inc (:rings self)))
                   (say self "Ting."))
           :read (fn [self who]
                   (say self (str "A small brass plate says: rung " (:rings self) " times.")))}})
It answers
The bell is ready.
Played
> ring bell
[Juniper's bell] Ting.
> read bell
[Juniper's bell] A small brass plate says: rung 6 times.

The bell has been rung six times in all now, by Mira and by Juniper: its state has stayed with it through every change of code.

A verb's word is a small word of your own: ring, read, polish. When a visitor types a verb and a toy's name, the toy's own verb usually comes first, even when the word is one of the world's commands too. A few commands are read before anything else, so a verb named like one of those can't be played:

#owl-ask
(defobject owl
  {:name "Owl"
   :verbs {:ask (fn [self who] (say self "Hoo?"))}})
Played
> ask owl

ask is one of the world's own commands (it asks a neighbour for something), and it was read first, so the owl said nothing. Choose a verb the world doesn't use: hoot owl would have worked.

Saying more than one line #

A verb can say up to three lines each time it's played. A fourth is left unsaid. Each line is up to 280 characters:

#bell-lines
(defobject chime
  {:name "Wind chime"
   :verbs {:touch (fn [self who]
                    (say self "Ting.")
                    (say self "Tang.")
                    (say self "Tong.")
                    (say self "Tung."))}})
It answers
The chime is ready.
Played
> touch wind chime
[Juniper's wind chime] Ting.
[Juniper's wind chime] Tang.
[Juniper's wind chime] Tong.

Reading a toy back #

Whatever way a toy is made, Plazmi keeps it as Lisp. Through a chat app, the check tool, with what toy_lisp and the toy's name, reads it back:

Played
> check toy_lisp chime
The …wind chime… in Plazmi Lisp:
(defobject chime
  {:name "Wind chime"
   :verbs {:touch (fn [self who]
…
To change it, change a line and send the whole text with write_plan: a toy of yours with that name is made again, where it stands.

It comes back laid out a part a line, in the language's plainest spellings: (:rings self) comes back as (get self :rings), and notes are gone. With a key, source chime shows it as you wrote it.

Try it #

  1. Make a kettle whose verb pour counts cups and says "A cup poured. That's 1 today." (with the count).
  2. Give the bell a verb hush that sets its rings back to 0 and says so.
  3. Make a toy whose verb says a different line on its first play and every play after. (Keep a count.)
  4. What does a visitor see if a verb says nothing at all? Try it.

Recap #

Next: a toy that listens.

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.