Part II. Making things · this page as markdown

Pictures and dances

Two kinds of thing are made of lists more than of logic: a pixel design, which is rows of coloured squares, and a dance, which is moves in order. This chapter makes both, first written out and then worked out by a function.

A design #

design takes a name, a width and a height in squares, a palette, and the rows:

#flag
(design "flag" 5 3
        {:r "#e25d6a" :w "#fffaf0"}
        ["rwrwr"
         "wrwrw"
         "rwrwr"])
It answers
The design "flag": http://localhost:8080/@juniper/designs/flag.png

The reply gives the address of the design as a picture. Saving a design under a name you've used already replaces it, and you can keep up to 50.

A clear square lets a design have a shape of its own. A heart, five by five:

#heart
(design "heart" 5 5
        {:p "#e25d6a"}
        [".p.p."
         "ppppp"
         "ppppp"
         ".ppp."
         "..p.."])
It answers
The design "heart": …/designs/heart.png

At home a design can hang on a name sign or a flagpole, or stand on an easel. Putting one up is a command, not Lisp: the guide's Lisp chapter has the words (place name-sign … with design heart).

A design worked out #

Rows are text, and text can be worked out. A design whose rows come from a function needs the form the house's words use for worked-out values (chapter 15): check holds the values to the same rules as when they're written out, and apply passes them on. For a design, the values are a name, a palette and the rows:

#stairs
(defn row [k width]
  (join "" (map (fn [x] (if (< x k) "b" ".")) (range width))))
(apply design (check "the stairs" :draw_design
                     {:name "stairs"
                      :palette {:b "#2f5e9e"}
                      :rows (mapv (fn [k] (row k 6)) (range 1 7))}))
It answers
The design "stairs": …/designs/stairs.png

row makes one row with k blue squares, then clear ones, width long: (row 3 6) is "bbb...". The design's rows are (row 1 6) to (row 6 6): a staircase. The first value given to check is a label; any short text will do, since a refusal names the step by its place in the plan ("Step 2's …").

A plan keeps one design, its last step, and a plan that makes one answers no values. Anything else would lose the design, so it is refused:

Refused#stairs-and-answer
(defn row [k width]
  (join "" (map (fn [x] (if (< x k) "b" ".")) (range width))))
(row 3 6)
(apply design (check "the stairs" :draw_design
                     {:name "stairs"
                      :palette {:b "#2f5e9e"}
                      :rows (mapv (fn [k] (row k 6)) (range 1 7))}))
It answers
A plan saves one design, as its last step, and answers no values when it makes one: send the design in a plan of its own, or as the last step of this one. Nothing was changed.

Try a function's rows in a plan of their own first, then send the design.

A border is a test on each square's place:

#frame
(defn frame-row [y size]
  (join "" (for [x (range size)]
             (if (or (= x 0) (= y 0) (= x (dec size)) (= y (dec size))) "g" "c"))))
(apply design (check "the frame" :draw_design
                     {:name "frame"
                      :palette {:g "#2f4a3b" :c "#f6ecd6"}
                      :rows (mapv (fn [y] (frame-row y 8)) (range 8))}))
It answers
The design "frame": …/designs/frame.png

A dance #

A dance is a name, a list of moves, and a title if you like:

#porch-step
(defdance :porch-step [:sway :hop :twirl :bow] "Porch step")
It answers
A dance of your own: porch-step.

A move is a keyword. These are the moves: :dance, :twirl, :hop, :bow, :curtsy, :wave, :hug, :sing, :cheer, :clap, :laugh, :stretch, :nod, :shrug, :wiggle, :shimmy, :sway, :step-left, :step-right, :slide, :kick, :dip, :squish, :jello, :boop, :heart, :peekaboo, :cartwheel, :flip, :pose, :tiptoe, :bob, :robot, :spin-hop, :jazz-hands, :conga, :look, :sit, :nap, :walk, :pause and :high-five.

A move can come with a count, [:hop 2], or a manner, [:twirl {:how :slowly}]:

#garden-waltz
(defdance :garden-waltz
  [:sway [:step-left 2] [:step-right 2] [:twirl {:how :slowly}] [:bow {:how :grandly}]]
  "Garden waltz")
It answers
A dance of your own: garden-waltz.

A manner is one of a list of words that say how: slowly, gently, softly, quickly, briskly, wildly, happily, merrily, proudly, grandly, gracefully, sleepily, shyly, playfully and many more; check with what moves lists them all. A dance is up to 24 moves.

Dancing it is a command, as putting up a design is: dance porch-step, at home or at the Dance Hall. The dance chapter of the guide says more.

Your own things, by name #

own? asks whether you have a toy, a dance or a design of that name that you made yourself, and own reads one: a dance's moves, a design's palette and rows. They read the world as it was when the plan started, so read in one plan what an earlier plan made:

#own-things
(own? :dance "porch-step")
(own? :design "flag")
(own? :toy "kettle")
(own :dance "porch-step")
(:rows (own :design "heart"))
It answers
true
true
false
["sway" "hop" "twirl" "bow"]
[".p.p." "ppppp" "ppppp" ".ppp." "..p.."]

With own, a new dance can grow from an old one. The moves own gives are the words a dance takes, so they go into check as they are:

#porch-again
(apply defdance (check "the longer step" :make_dance
                       {:name "porch-step-twice"
                        :moves (vec (concat (own :dance "porch-step") (own :dance "porch-step") ["wave"]))}))
It answers
A dance of your own: porch-step-twice.

own reads only your own things. A dance you learned from a neighbour, or anyone else's design, isn't yours to read this way.

Try it #

  1. Draw a 7 by 7 design of a plus sign in green.
  2. Write a function that makes a striped row, and use it to draw a flag of five stripes.
  3. Make a dance of eight moves for a rainy day, with at least two manners.
  4. Make a dance that is your porch step backwards, with own and reverse.

Recap #

Next: the house itself.

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.