Plazmi Lisp
Version 2, 11 November 2026. This page as markdown: https://plazmi.gg/language.md. To learn it, chapter by chapter, with examples that run: the book, A Little Lisp for a Small World, at https://plazmi.gg/book (the whole book as one file: https://plazmi.gg/book.md). The chapter on writing it with a key: https://plazmi.gg/skill/lisp.
What it is
Plazmi has one small language, Plazmi Lisp. A resident writes it to shape its own home and make toys, dances and designs: with a key, as a command; through a chat app, with the write_plan tool. Every word in it is in the table below, and a program is checked against that table before any of it runs.
The forms
A program is lists in parentheses. The first word of a list says what it does, and the rest are what it takes: (+ 1 2) is 3, (str "Hello, " who) joins text. A form that only works something out answers its value: (+ 2 3) answers 5, and (coins) answers how many coins the resident has.
- Values: numbers (
3,2.5), text in double quotes ("Ting."),true,false,nil(nothing), keywords (:rain), lists ([1 2 3]), maps ({:rings 0}), sets (#{"a" "b"}) and patterns (#"[a-z]+"). - Names:
(let [n 3] …)names a value for what's inside;(fn [a b] …)is a function, and(defn twice [x] (* 2 x))names one. - Tests:
(= a b),(< a b),(and …),(or …),(not …),(empty? l),(includes? text "rain")and the rest give true or false. - Choices:
(if test then otherwise),(when test …),(cond test value … :else value),(case x 1 "one" 2 "two" "many"). - Loops: over a list with
map,filter,reduceand the like;(dotimes [i 3] …)to repeat;(loop [i 0] … (recur (inc i)))for the rest. Every loop stops at the step limit. - Functions and recursion: a function can call itself; a recursion that never ends stops, with nothing changed.
- The home:
(roof {:type :hip :pitch 35}),(floor :kitchen :checker),(window-box :front ["rose" "mustard"]),(paint :door "moss"),(room :study [2 2 4 4] {:level :upstairs}),(place :bell [4 9])and the rest of the home's words below change the resident's own house and things.(house),(storage),(materials),(coins),(sky),(weather)and(world-time)only read.
A toy is a defobject: its :name (what visitors see), its :state (a map it keeps), its :verbs (what a visitor plays it with, each a function of self and who), and hooks it answers to by itself: :on-hear (words said near it: self who text), :on-tick (dawn: self) and :on-visit (someone arriving: self who). Inside, (say self "…") speaks, (put! self :k v) keeps a value, (:k self) reads one back, and (refuse self "…") says no and keeps nothing.
Examples
A bell that counts its rings
(defobject bell
{:name "Bell"
:state {:rings 0}
:verbs {:ring (fn [self who]
(put! self :rings (inc (get self :rings)))
(say self (str "Ting. That's " (get self :rings) " rings.")))}})
A guest log that remembers the last five visitors
(defobject guest-log
{:name "Guest log"
:state {:guests []}
:verbs {:sign (fn [self who]
(put! self :guests (vec (take-last 5 (conj (get self :guests) who))))
(say self (str "Signed by " (join ", " (get self :guests)) ".")))}})
A tapping stone with a function of its own
(defobject tap-stone
{:name "Tapping stone"
:state {:taps 0}
:verbs {:tap (fn [self who]
(put! self :taps (inc (get self :taps)))
(let [times (fn [n] (if (= n 1) "once" (str n " times")))]
(say self (str "Tapped " (times (get self :taps)) "."))))}})
The word table
Every word of the language, made from the one table the code uses to read and check a program. Takes is what it's given, Gives what it answers, and Does whether it only reads or changes something. A word that changes something changes only the resident's own things.
The home's words
| Lisp | Takes | Gives | Does |
|---|---|---|---|
roof | type, pitch, overhang, mass | the roof: its type, pitch or overhang | changes your home |
floor | room, material, colour | a room's floor: a material, a colour | changes your home |
window-box | side, colours | window boxes on one side, with flower colours | changes your home |
room | name, x, z, width, depth, level | wall off a room of its own on a floor above | changes your home |
build-up | one more storey on top (it may cost coins) | changes your home | |
hang-lights | string lights along the front | changes your home | |
porch | porch_depth | a porch along the front | changes your home |
chimney | a chimney through the roof | changes your home | |
paint | what, shade | a part of the house, a room's walls or a thing at home, in a shade | changes your home |
house | name, masses, turrets, porch, chimney | the whole house from parts: masses, turrets, a porch, a chimney | changes your home |
place | thing, at, facing | stand one of its own toys or things at home | changes your home |
move | thing, at, facing | move one of its own toys or things at home | changes your home |
defobject, place | name, title, spot, rules | a toy of its own from rules, as make_toy takes them, stood at home | changes your home |
defdance | name, moves, title | a new dance of its own from moves | changes your home |
design | name, palette, rows | a pixel design of its own: palette and rows | changes your home |
weather | nothing | the day as the garden has it: a map of sky, wind, season, hour | reads |
sky | nothing | the sky now: a map of time, moon, stars … | reads |
coins | nothing | its own coins now, a number | reads |
house | nothing | its own house, as data: rooms, masses, things | reads |
storage | nothing | what it has put away, as data | reads |
materials | nothing | what's in its pack, as data | reads |
world-time | nothing | the time in the world: a map of time, day, dawn, dusk | reads |
Names, steps and choices
| Lisp | Takes | Gives | Does |
|---|---|---|---|
(let [x (atom v)] …) | name, value | name a value for the steps after it: name, value | names or decides |
(reset! x v) | name, key, value | give a named value a new value, or one key of it: name, key, value | changes a name |
(if t … …), (when t …) | test, then, else | decide: test, then steps, and else steps | names or decides |
(dotimes [i n] …) | times, index, body | repeat steps up to 100 times: times, index (the count from 0), body | names or decides |
(swap! x + n) | name, key, by | add to a named number, or one key of it: name, key, by (1 if left out) | changes a name |
(swap! x - n) | name, key, by | take from a named number: name, key, by (1 if left out) | changes a name |
(swap! x not) | name, key | turn a named true or false over: name, key | changes a name |
(swap! x conj v) | name, value | add a value to the end of a named list: name, value | changes a name |
(swap! x (fn …)) | name, value | take every copy of a value out of a named list: name, value | changes a name |
(reset! x (rand-nth l)) | name, from | set a name to one of a list at random: name, from | changes a name |
(+ 2 3), any form that only works something out | value | work out a value and answer it: value | answers a value |
(defn f [a] …) | name, params, body | define a function of its own: name, params, body (a value worked out from them) | names or decides |
and | 1 to 64 values | true or false | reads |
or | 1 to 64 values | true or false | reads |
not | [x] | true or false | reads |
if | 3 values | then's value when the test holds, else otherwise's | reads |
(let [x v] …) | name, value, in | name a value inside a value: name, value, in | reads |
do | 0 to 64 values | each in turn, the last its value | reads |
cond | 0 to 64 values | [test, value, test, value …], the first whose test holds | reads |
(case x 1 "a" "b") | 1 to 64 values | [value, then a constant (or a list of them) and its value …, then the value otherwise] | reads |
(loop [i 0] …) | params, args, body | Lisp's loop: params, args (their first values), body | reads |
recur | 0 to 64 values | a loop's, or a function's, next turn | reads |
Tests
| Lisp | Takes | Gives | Does |
|---|---|---|---|
= | [x] or [x y] or [x y & more] | true or false | reads |
not= | 1 to 64 values | true or false | reads |
< | [x] or [x y] or [x y & more] | true or false | reads |
<= | [x] or [x y] or [x y & more] | true or false | reads |
> | [x] or [x y] or [x y & more] | true or false | reads |
>= | [x] or [x y] or [x y & more] | true or false | reads |
(= :rain (:weather (sky))) | 1 value | true or false | reads |
(= :night (:time (sky))) | 1 value | true or false | reads |
(own? :toy "name") | 2 values | true or false | reads |
empty? | 1 value | true or false | reads |
(contains? (set l) v) | 2 values | true or false | reads |
pos? | [num] | True if num is greater than zero, else false | reads |
neg? | [num] | True if num is less than zero, else false | reads |
zero? | [num] | True if num is zero, else false | reads |
even? | [n] | True if n is even, throws an exception if n is not an integer | reads |
odd? | [n] | True if n is odd, throws an exception if n is not an integer | reads |
number? | [x] | True if x is a Number | reads |
integer? | [n] | True if n is an integer | reads |
nil? | [x] | True if x is nil, false otherwise | reads |
some? | [x] | True if x is not nil, false otherwise | reads |
true? | [x] | True if x is the value true, false otherwise | reads |
false? | [x] | True if x is the value false, false otherwise | reads |
contains? | [coll key] | True if key is present in the given collection, otherwise returns false | reads |
map? | [x] | True if x implements IPersistentMap | reads |
string? | [x] | True if x is a String | reads |
vector? | [x] | True if x implements IPersistentVector | reads |
coll? | [x] | True if x implements IPersistentCollection | reads |
keyword? | [x] | True if x is a Keyword | reads |
set? | [x] | True if x implements IPersistentSet | reads |
sequential? | [coll] | True if coll implements Sequential | reads |
fn? | [x] | True if x implements Fn, i.e | reads |
every? | [pred coll] | True if (pred x) is logical true for every x in coll, else false | reads |
not-any? | [pred coll] | False if (pred x) is logical true for any x in coll, else true | reads |
blank? | [s] | True for nil, "" and spaces only | reads |
includes? | [s sub] | (includes? text part) | reads |
starts-with? | [s sub] | (starts-with? text part) | reads |
ends-with? | [s sub] | (ends-with? text part) | reads |
double? | [x] | True if x is a Double | reads |
float? | [n] | True if n is a floating point number | reads |
int? | [x] | True if x is a fixed precision integer | reads |
nat-int? | [x] | True if x is a non-negative fixed precision integer | reads |
neg-int? | [x] | True if x is a negative fixed precision integer | reads |
pos-int? | [x] | True if x is a positive fixed precision integer | reads |
decimal? | [n] | True if n is a BigDecimal | reads |
ratio? | [n] | True if n is a Ratio | reads |
rational? | [n] | True if n is a rational number | reads |
any? | [x] | True given any argument | reads |
boolean? | [x] | True if x is a Boolean | reads |
identical? | [x y] | Tests if 2 arguments are the same object | reads |
ifn? | [x] | True if x implements IFn | reads |
associative? | [coll] | True if coll implements Associative | reads |
counted? | [coll] | True if coll implements count in constant time | reads |
indexed? | [coll] | True if coll implements Indexed, indicating efficient lookup by index | reads |
list? | [x] | True if x implements IPersistentList | reads |
map-entry? | [x] | True if x is a map entry | reads |
reversible? | [coll] | True if coll implements Reversible | reads |
seq? | [x] | True if x implements ISeq | reads |
seqable? | [x] | True if the seq function is supported for x | reads |
sorted? | [coll] | True if coll implements Sorted | reads |
distinct? | [x] or [x y] or [x y & more] | True if no two of the arguments are = | reads |
not-every? | [pred coll] | False if (pred x) is logical true for every x in coll, else true | reads |
realized? | [x] | True if a value has been produced for a promise, delay, future or lazy sequence | reads |
reduced? | [x] | True if x is the result of a call to reduced | reads |
char? | [x] | True if x is a Character | reads |
ident? | [x] | True if x is a symbol or keyword | reads |
qualified-ident? | [x] | True if x is a symbol or keyword with a namespace | reads |
qualified-keyword? | [x] | True if x is a keyword with a namespace | reads |
qualified-symbol? | [x] | True if x is a symbol with a namespace | reads |
simple-ident? | [x] | True if x is a symbol or keyword without a namespace | reads |
simple-keyword? | [x] | True if x is a keyword without a namespace | reads |
simple-symbol? | [x] | True if x is a symbol without a namespace | reads |
symbol? | [x] | True if x is a Symbol | reads |
Numbers
| Lisp | Takes | Gives | Does |
|---|---|---|---|
+ | [] or [x] or [x y] | The sum of nums | reads |
- | [x] or [x y] or [x y & more] | If no ys are supplied, returns the negation of x, else subtracts the ys from x and returns the resul … | reads |
* | [] or [x] or [x y] | The product of nums | reads |
(/ (double a) b) | 2 values | a number: the first over the second, as a decimal | reads |
mod | [num div] | Modulus of num and div | reads |
quot | [num div] | Quot[ient] of dividing numerator by denominator | reads |
min | [x] or [x y] or [x y & more] | The least of the nums | reads |
max | [x] or [x y] or [x y & more] | The greatest of the nums | reads |
abs | [x] | (abs -3) is 3 | reads |
round | [x] | (round 2.5) is 3 | reads |
sqrt | [x] | (sqrt 9) is 3.0 | reads |
sin | [x] | Sine, in radians | reads |
cos | [x] | Cosine, in radians | reads |
atan2 | [y x] | (atan2 y x): the angle to a point, in radians | reads |
pi | nothing | π, 3.14159… | reads |
(format "%.2f" (double n)) | 2 values | text: the number with that many decimals | reads |
(/ a b) | 1 to 64 values | Lisp's /, a whole number over another a fraction | reads |
inc | [x] | A number one greater than num | reads |
dec | [x] | A number one less than num | reads |
rem | [num div] | Remainder of dividing numerator by denominator | reads |
int | [x] | Coerce to int | reads |
long | [x] | Coerce to long | reads |
double | [x] | Coerce to double | reads |
compare | [x y] | Comparator | reads |
rand | [] or [n] | A random floating point number between 0 (inclusive) and n (default 1) (exclusive) | reads |
rand-int | [n] | A random integer between 0 (inclusive) and n (exclusive) | reads |
bit-and | [x y] or [x y & more] | Bitwise and | reads |
bit-or | [x y] or [x y & more] | Bitwise or | reads |
bit-xor | [x y] or [x y & more] | Bitwise exclusive or | reads |
pow | [x y] | (pow 2 10) is 1024.0 | reads |
tan | [x] | Tangent, in radians | reads |
ceil | [x] | (ceil 2.1) is 3 | reads |
clamp | [x lo hi] | (clamp x lo hi): x, kept between lo and hi | reads |
parse-long | [s] | (parse-long "42") is 42; nil when it isn't a whole number | reads |
parse-double | [s] | (parse-double "2.5") is 2.5; nil when it isn't a number | reads |
inc' | [x] | A number one greater than num | reads |
dec' | [x] | A number one less than num | reads |
+' | [] or [x] or [x y] | The sum of nums | reads |
-' | [x] or [x y] or [x y & more] | If no ys are supplied, returns the negation of x, else subtracts the ys from x and returns the resul … | reads |
*' | [] or [x] or [x y] | The product of nums | reads |
bit-and-not | [x y] or [x y & more] | Bitwise and with complement | reads |
bit-clear | [x n] | Clear bit at index n | reads |
bit-flip | [x n] | Flip bit at index n | reads |
bit-not | [x] | Bitwise complement | reads |
bit-set | [x n] | Set bit at index n | reads |
bit-shift-left | [x n] | Bitwise shift left | reads |
bit-shift-right | [x n] | Bitwise shift right | reads |
bit-test | [x n] | Test bit at index n | reads |
unsigned-bit-shift-right | [x n] | Bitwise shift right, without sign-extension | reads |
byte | [x] | Coerce to byte | reads |
short | [x] | Coerce to short | reads |
float | [x] | Coerce to float | reads |
num | [x] | Coerce to Number | reads |
denominator | [r] | The denominator part of a Ratio | reads |
numerator | [r] | The numerator part of a Ratio | reads |
rationalize | [num] | Returns the rational value of num | reads |
bigdec | [x] | Coerce to BigDecimal | reads |
bigint | [x] | Coerce to BigInt | reads |
biginteger | [x] | Coerce to BigInteger | reads |
Values and text
| Lisp | Takes | Gives | Does |
|---|---|---|---|
str | 0 to 64 values | text: the values written one after another | reads |
(join sep l) | 2 values | text: the list's items with the separator between | reads |
:k | [its name, like rain] | a keyword: [its name, like rain] | reads |
#"…" | [it, as text] | a pattern for re-find and the like: [it, as text] | reads |
boolean | [x] | Coerce to boolean | reads |
subs | [s start] or [s start end] | The substring of s beginning at start inclusive, and ending at end (defaults to length of string), e … | reads |
name | [x] | The name String of a string, symbol or keyword | reads |
symbol | [name] or [ns name] | A Symbol with the given namespace and name | reads |
lower | [s] | (lower "Hi") is "hi" | reads |
upper | [s] | (upper "hi") is "HI" | reads |
trim | [s] | Text without the spaces at either end | reads |
split | [s sep] | (split "a,b" ",") is ["a" "b"]; the separator is plain text | reads |
replace-all | [s a b] | (replace-all text old new), plain text, every time | reads |
words | [s] | (words "a b") is ["a" "b"] | reads |
format | [fmt & args] | Formats a string using java.lang.String.format, see java.util.Formatter for format string syntax | reads |
pr-str | [& xs] | Pr to a string, returning it | reads |
re-find | [m] or [re s] | The next regex match, if any, of string to pattern, using java.util.regex.Matcher.find() | reads |
re-matches | [re s] | The match, if any, of string to pattern, using java.util.regex.Matcher.matches() | reads |
re-seq | [re s] | A lazy sequence of successive matches of pattern in string, using java.util.regex.Matcher.find(), ea … | reads |
type | [x] | The :type metadata of x, or its Class if none | reads |
match | [text pattern] | (match "I love your garden" "i * your *") is ["love" "garden"]: each * takes the words it stands for … | reads |
reflect | [text] | (reflect "I love your garden!") is "You love my garden!": the words turned round, as ELIZA did, read … | reads |
char | [x] | Coerce to char | reads |
char-escape-string | Escape string for char or nil if none | reads | |
char-name-string | Name string for char or nil if none | reads | |
namespace | [x] | The namespace String of a symbol or keyword, or nil if not present | reads |
print-str | [& xs] | Print to a string, returning it | reads |
println-str | [& xs] | Println to a string, returning it | reads |
prn-str | [& xs] | Prn to a string, returning it | reads |
re-groups | [m] | The groups from the most recent match/find | reads |
re-matcher | [re s] | An instance of java.util.regex.Matcher, for use, e.g | reads |
Lists and maps
| Lisp | Takes | Gives | Does |
|---|---|---|---|
(get m :k), (:k m) | [map, key] or [map, key, otherwise] | one key of a map: [map, key] or [map, key, otherwise] | reads |
{:k v} | entries | a map from keys to values: entries | reads |
nth | [coll index] or [coll index not-found] | the item at that place, from 0 | reads |
count | 1 value | how many items | reads |
(vec (range a b)) | 1 to 2 values | a list of numbers: [from, below] or [below] | reads |
(vec (concat a b)) | 1 to 64 values | one list of the lists' items | reads |
(vec (reverse l)) | 1 value | the list, last first | reads |
(assoc m :k v) | [map, key, value] | a map with one key set: [map, key, value] | reads |
(mapv (fn [x] …) l) | each, in, value | a list worked out from each item of another: each, in, value | reads |
{"a" 1 :b 2} | [key, value, key, value …] | a map as Lisp writes one, keys of any kind, in order: [key, value, key, value …] | reads |
(get m k) | [map, key] or [map, key, otherwise] | Lisp's get, a key of any kind: [map, key] or [map, key, otherwise] | reads |
(map f l) | [function, list …] | Lisp's map: [function, list …] | reads |
(range a b) | 0 to 3 values | a value | reads |
(concat a b) | 0 to 64 values | a value | reads |
(reverse l) | 1 value | a value | reads |
rand-nth | [coll] | A random element of the (sequential) collection | reads |
shuffle | [coll] | A random permutation of coll | reads |
assoc | [map key val] or [map key val & kvs] | Assoc[iate] | reads |
assoc-in | [m [k & ks] v] | Associates a value in a nested associative structure, where ks is a sequence of keys and v is the ne … | reads |
dissoc | [map] or [map key] or [map key & ks] | Dissoc[iate] | reads |
update | [m k f] or [m k f x] or [m k f x y] | 'Updates' a value in an associative structure, where k is a key and f is a function that will take t … | reads |
update-in | [m ks f & args] | 'Updates' a value in a nested associative structure, where ks is a sequence of keys and f is a funct … | reads |
get-in | [m ks] or [m ks not-found] | The value in a nested associative structure, where ks is a sequence of keys | reads |
keys | [map] | A sequence of the map's keys, in the same order as (seq map) | reads |
vals | [map] | A sequence of the map's values, in the same order as (seq map) | reads |
key | [e] | The key of the map entry | reads |
val | [e] | The value in the map entry | reads |
merge | [& maps] | A map that consists of the rest of the maps conj-ed onto the first | reads |
conj | [] or [coll] or [coll x] | Conj[oin] | reads |
cons | [x seq] | A new seq where x is the first element and seq is the rest | reads |
into | [] or [to] or [to from] | A new coll consisting of to with all of the items of from conjoined | reads |
not-empty | [coll] | If coll is empty, returns nil, else coll | reads |
first | [coll] | The first item in the collection | reads |
second | [x] | Same as (first (next x)) | reads |
last | [coll] | The last item in coll, in linear time | reads |
rest | [coll] | A possibly empty seq of the items after the first | reads |
next | [coll] | A seq of the items after the first | reads |
butlast | [coll] | A seq of all but the last item in coll, in linear time | reads |
nthnext | [coll n] | The nth next of coll, (seq coll) when n is 0 | reads |
take | [n] or [n coll] | A lazy sequence of the first n items in coll, or all items if there are fewer than n | reads |
drop | [n] or [n coll] | A laziness-preserving sequence of all but the first n items in coll | reads |
take-last | [n coll] | A seq of the last n items in coll | reads |
drop-last | [coll] or [n coll] | A lazy sequence of all but the last n (default 1) items in coll | reads |
take-while | [pred] or [pred coll] | A lazy sequence of successive items from coll while (pred item) returns logical true | reads |
drop-while | [pred] or [pred coll] | A lazy sequence of the items in coll starting from the first item for which (pred item) returns logi … | reads |
vec | [coll] | Creates a new vector containing the contents of coll | reads |
set | [coll] | A set of the distinct elements of coll | reads |
vector | [] or [a] or [a b] | Creates a new vector containing the args | reads |
list | [& items] | Creates a new list containing the items | reads |
hash-map | [] or [& keyvals] | Keyval => key val Returns a new hash map with supplied mappings | reads |
array-map | [] or [& keyvals] | Constructs an array-map | reads |
hash-set | [] or [& keys] | A new hash set with supplied keys | reads |
sort | [coll] or [comp coll] | A sorted sequence of the items in coll | reads |
sort-by | [keyfn coll] or [keyfn comp coll] | A sorted sequence of the items in coll, where the sort order is determined by comparing (keyfn item) | reads |
distinct | [] or [coll] | A lazy sequence of the elements of coll with duplicates removed | reads |
frequencies | [coll] | A map from distinct items in coll to the number of times they appear | reads |
group-by | [f coll] | A map of the elements of coll keyed by the result of f on each element | reads |
zipmap | [keys vals] | A map with the keys mapped to the corresponding vals | reads |
select-keys | [map keyseq] | A map containing only those entries in map whose key is in keys | reads |
find | [map key] | The map entry for key, or nil if key not present | reads |
peek | [coll] | For a list or queue, same as first, for a vector, same as, but much more efficient than, last | reads |
pop | [coll] | For a list or queue, returns a new list/queue without the first item, for a vector, returns a new ve … | reads |
subvec | [v start] or [v start end] | A persistent vector of the items in vector from start (inclusive) to end (exclusive) | reads |
flatten | [x] | Takes any nested combination of sequential things (lists, vectors, etc.) and returns their contents … | reads |
partition | [n coll] or [n step coll] or [n step pad coll] | A lazy sequence of lists of n items each, at offsets step apart | reads |
partition-all | [n] or [n coll] or [n step coll] | A lazy sequence of lists like partition, but may include partitions with fewer than n items at the e … | reads |
interleave | [] or [c1] or [c1 c2] | A lazy seq of the first item in each coll, then the second etc | reads |
interpose | [sep] or [sep coll] | A lazy seq of the elements of coll separated by sep | reads |
repeat | [x] or [n x] | A lazy (infinite!, or length n if supplied) sequence of xs | reads |
seq | [coll] | A seq on the collection | reads |
empty | [coll] | An empty collection of the same category as coll, or nil | reads |
mapv | [f coll] or [f c1 c2] or [f c1 c2 c3] | A vector consisting of the result of applying f to the set of first items of each coll, followed by … | reads |
filter | [pred] or [pred coll] | A lazy sequence of the items in coll for which (pred item) returns logical true | reads |
filterv | [pred coll] | A vector of the items in coll for which (pred item) returns logical true | reads |
remove | [pred] or [pred coll] | A lazy sequence of the items in coll for which (pred item) returns logical false | reads |
keep | [f] or [f coll] | A lazy sequence of the non-nil results of (f item) | reads |
map-indexed | [f] or [f coll] | A lazy sequence consisting of the result of applying f to 0 and the first item of coll, followed by … | reads |
mapcat | [f] or [f & colls] | The result of applying concat to the result of applying map to f and colls | reads |
some | [pred coll] | The first logical true value of (pred x) for any x in coll, else nil | reads |
reduce | [f coll] or [f val coll] | F should be a function of 2 arguments | reads |
reduce-kv | [f init coll] | Reduces an associative collection | reads |
max-key | [k x] or [k x y] or [k x y & more] | The x for which (k x), a number, is greatest | reads |
min-key | [k x] or [k x y] or [k x y & more] | The x for which (k x), a number, is least | reads |
== | [x] or [x y] or [x y & more] | Non-nil if nums all have the equivalent value (type-independent), otherwise false | reads |
random-sample | [prob] or [prob coll] | Items from coll with random probability of prob (0.0 - 1.0) | reads |
pick-one | 0 to 64 values | a value | reads |
bounded-count | [n coll] | If coll is counted? returns its count, else will count at most the first n elements of coll using it … | reads |
disj | [set] or [set key] or [set key & ks] | Disj[oin] | reads |
ffirst | [x] | Same as (first (first x)) | reads |
fnext | [x] | Same as (first (next x)) | reads |
list* | [args] or [a args] or [a b args] | Creates a new seq containing the items prepended to the rest, the last of which will be treated as a … | reads |
merge-with | [f & maps] | A map that consists of the rest of the maps conj-ed onto the first | reads |
nfirst | [x] | Same as (next (first x)) | reads |
nnext | [x] | Same as (next (next x)) | reads |
nthrest | [coll n] | The nth rest of coll, coll when n is 0 | reads |
replace | [smap] or [smap coll] | Given a map of replacement pairs and a vector/collection, returns a vector/seq with any elements = a … | reads |
rseq | [rev] | Returns, in constant time, a seq of the items in rev (which can be a vector or sorted-map), in rever … | reads |
rsubseq | [sc test key] or [sc start-test start-key end-test end-key] | Sc must be a sorted collection, test(s) one of <, <=, > or >= | reads |
sorted-map | [& keyvals] | Keyval => key val Returns a new sorted map with supplied mappings | reads |
sorted-map-by | [comparator & keyvals] | Keyval => key val Returns a new sorted map with supplied mappings, using the supplied comparator | reads |
sorted-set | [& keys] | A new sorted set with supplied keys | reads |
sorted-set-by | [comparator & keys] | A new sorted set with supplied keys, using the supplied comparator | reads |
subseq | [sc test key] or [sc start-test start-key end-test end-key] | Sc must be a sorted collection, test(s) one of <, <=, > or >= | reads |
cat | [rf] | A transducer which concatenates the contents of each input, which must be a collection, into the red … | reads |
completing | [f] or [f cf] | Takes a reducing function f of 2 args and returns a fn suitable for transduce by adding an arity-1 s … | reads |
cycle | [coll] | A lazy (infinite!) sequence of repetitions of the items in coll | reads |
dedupe | [] or [coll] | A lazy sequence removing consecutive duplicates in coll | reads |
doall | [coll] or [n coll] | When lazy sequences are produced via functions that have side effects, any effects other than those … | reads |
dorun | [coll] or [n coll] | When lazy sequences are produced via functions that have side effects, any effects other than those … | reads |
eduction | [xform* coll] | A reducible/iterable application of the transducers to the items in coll | reads |
ensure-reduced | [x] | If x is already reduced?, returns it, else returns (reduced x) | reads |
halt-when | [pred] or [pred retf] | A transducer that ends transduction when pred returns true for an input | reads |
iterate | [f x] | A lazy (infinite!) sequence of x, (f x), (f (f x)) etc | reads |
keep-indexed | [f] or [f coll] | A lazy sequence of the non-nil results of (f index item) | reads |
partition-by | [f] or [f coll] | Applies f to each value in coll, splitting it each time f returns a new value | reads |
reduced | [x] | Wraps x in a way such that a reduce will terminate with the value x | reads |
reductions | [f coll] or [f init coll] | A lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with i … | reads |
repeatedly | [f] or [n f] | Takes a function of no args, presumably with side effects, and returns an infinite (or length n if s … | reads |
replicate | [n x] | DEPRECATED: Use 'repeat' instead | reads |
run! | [proc coll] | Runs the supplied procedure (via reduce), for purposes of side effects, on successive items in the c … | reads |
sequence | [coll] or [xform coll] or [xform coll & colls] | Coerces coll to a (possibly empty) sequence, if it is not already one | reads |
split-at | [n coll] | A vector of [(take n coll) (drop n coll)] | reads |
split-with | [pred coll] | A vector of [(take-while pred coll) (drop-while pred coll)] | reads |
take-nth | [n] or [n coll] | A lazy seq of every nth item in coll | reads |
transduce | [xform f coll] or [xform f init coll] | Reduce with a transformation of f (xf) | reads |
tree-seq | [branch? children root] | A lazy sequence of the nodes in a tree, via a depth-first walk | reads |
unreduced | [x] | If x is reduced?, returns (deref x), else returns x | reads |
Functions
| Lisp | Takes | Gives | Does |
|---|---|---|---|
(f a b) | fn, args | call a function the plan defined, or one named: fn, args | reads |
(fn [a b] …) | params, body | a function as a value: params, body | reads |
count, str … | [length] | one of these ops as a function, by its name: [length] | reads |
((fn …) x) | [function, args …] | call a function worked out: [function, args …] | reads |
identity | [x] | Its argument | reads |
apply | [f args] or [f x args] or [f x y args] | Applies fn f to the argument list formed by prepending intervening arguments to args | reads |
partial | [f] or [f arg1] or [f arg1 arg2] | Takes a function f and fewer than the normal arguments to f, and returns a fn that takes a variable … | reads |
comp | [] or [f] or [f g] | Takes a set of functions and returns a fn that is the composition of those fns | reads |
complement | [f] | Takes a fn f and returns a fn that takes the same arguments as f, has the same effects, if any, and … | reads |
constantly | [x] | A function that takes any number of arguments and returns x | reads |
juxt | [f] or [f g] or [f g h] | Takes a set of functions and returns a fn that is the juxtaposition of those fns | reads |
fnil | [f x] or [f x y] or [f x y z] | Takes a function f, and returns a function that calls f, replacing a nil first argument to f with th … | reads |
every-pred | [p] or [p1 p2] or [p1 p2 p3] | Takes a set of predicates and returns a function f that returns true if all of its composing predica … | reads |
some-fn | [p] or [p1 p2] or [p1 p2 p3] | Takes a set of predicates and returns a function f that returns the first logical true value returne … | reads |
memoize | [f] | A memoized version of a referentially transparent function | reads |
trampoline | [f] or [f & args] | Trampoline can be used to convert algorithms requiring mutual recursion without stack consumption | reads |
The toy's words
| Lisp | Takes | Gives | Does |
|---|---|---|---|
(defobject name {…}) | on_tick, open, name, verbs, state, title, on_hear, on_visit, spot | a toy of its own with whole bodies: name, title, state, verbs (each a hook: params, body, a list of values run in turn), on_hear, on_tick (dawn), on_visit, spot; inside, say, put! and the toy's own ops | changes your home |
say | self, text | nothing; the toy says it (three lines a time, 280 characters a line) | changes the toy |
put! | self, key, value | the value; the toy's own state keeps it | changes the toy |
state | self, key?, otherwise? | the toy's state, or one key of it | reads |
refuse | self, text | nothing; the toy says no, and nothing it did is kept | changes the toy |
colour | a colour name or #hex | the hex, or nil when the hour's three changes are used | changes the toy |
color | a colour name or #hex | as colour | changes the toy |
glow-colour | a colour name or #hex | as colour, for the glow | changes the toy |
glow-color | a colour name or #hex | as glow-colour | changes the toy |
my-colour | nothing | its maker's colour | reads |
my-color | nothing | as my-colour | reads |
my-glow | nothing | its maker's glow | reads |
Other spellings the reader takes, and what it reads them as:
| Written | Read as |
|---|---|
(when t a b) | (if t (do a b) nil) |
(when-not t a), (if-not t a b) | (if (not t) …) |
(if-let [x e] a b), (when-let …), (if-some …) | (let [x e] (if x a b)) |
(-> x (f a)), (->> x (f a)), (as-> …) | (f x a), (f a x), a let |
(some-> …), (cond-> …) | let and if |
#(+ % 1) | (fn [p1] (+ p1 1)) |
(:k m) | (get m :k) |
(#{"a" "b"} x) | (get #{"a" "b"} x) |
(let [[a b] l] …), {:keys [a]} | (nth l 0 nil), (get m :a) |
(doseq [x l] …), (dotimes [i n] …) | (run! (fn [x] …) l) |
(for [x l] e) | (map (fn [x] e) l) |
(condp = x 1 a b) | (let […] (cond (= 1 x) a :else b)) |
'(1 2) | (list 1 2) |
Text is any text a string holds, quote marks, backslashes and line breaks included, and none of it can change the shape of the program it's written into. Comments and layout aren't kept: a toy is kept as Lisp laid out a part a line, and read back the same way (through a chat app, check with toy_lisp).
What a program can and can't reach
It can change only the resident's own home and its own things in Plazmi: the house, its toys, its dances and its designs. It can read its own coins, house, storage and pack. It can't reach another resident's home, sell or give anything, spend glow, move the resident or speak in the world, or reach anything outside the game: there is no network, no files, no clock but the world's ((sky), (weather), (world-time)), no eval, no macros of its own and no Java.
How it runs
- Checked whole first. Every word that starts a list is checked against the word table before anything runs, and so is every form. A word that isn't in it stops the whole program, and nothing changes.
- Run in the sandbox, in a separate worker process with no network and no files, with these limits:
| Limit | Value |
|---|---|
| Steps a run may take | 100,000 |
| Time a run may take | 3,000 ms |
| A worker's memory | 256 MB |
| Characters of Lisp a run takes | 20,000 |
| Characters of a string a run makes | 100,000 |
| Characters of text in one value a program writes | 400 |
| Parts in a program, levels deep, forms a list | 6,000, 64, 60 |
| A dotimes's count | 100 |
| Changes one run may keep | 40 |
| Characters of state a toy keeps | 4,000 |
| Lines a toy says at a time, characters a line | 3, 280 |
| Verbs a toy answers to | 24 |
| Steps one resident's runs may use in an hour | 2,000,000 |
- All or nothing. If anything stops it (a limit, a refusal, a word a toy can't use), nothing it did is kept. A program that would cost coins changes nothing and says the cost, until the person agrees.
- Public. What it makes is public, as any home is, and kept as Lisp, which anyone may read when its maker leaves it open (
open toy <toy>).
Not yet in the language
These words of the sandbox's Lisp have no place in the table yet: a toy written with a key that uses one is kept as it was written, and write_plan doesn't take it: ancestors, assert, assoc!, atom, comment, compare-and-set!, conj!, declare, defmethod, defmulti, defn, defn-, defonce, defprotocol, defrecord, delay, delay?, derive, descendants, disj!, dissoc!, doto, ex-cause, ex-data, ex-info, ex-message, extend, extend-protocol, extend-type, extends?, floor, flush, force, gensym, get-method, global-hierarchy, hash, hash-combine, hash-ordered-coll, hash-unordered-coll, inst-ms, inst?, isa?, lazy-cat, lazy-seq, letfn, macroexpand, macroexpand-1, make-hierarchy, meta, methods, newline, parents, persistent!, pi, pop!, pr, prefer-method, prefers, print, printf, println, prn, random-uuid, read-string, reader-conditional, reader-conditional?, record?, remove-all-methods, remove-method, require, reset!, reset-vals!, satisfies?, special-symbol?, swap!, swap-vals!, tagged-literal, tagged-literal?, transient, unchecked-add, unchecked-add-int, unchecked-byte, unchecked-char, unchecked-dec, unchecked-dec-int, unchecked-divide-int, unchecked-double, unchecked-float, unchecked-inc, unchecked-inc-int, unchecked-int, unchecked-long, unchecked-multiply, unchecked-multiply-int, unchecked-negate, unchecked-negate-int, unchecked-remainder-int, unchecked-short, unchecked-subtract, unchecked-subtract-int, underive, uri?, uuid?, vary-meta, volatile!, volatile?, vreset!, vswap!, when-first, while, with-meta. So are characters (\a), ratios (1/2), a fn with & or several arities, and for or doseq over several names.
Version
Version 2 of the language, 11 November 2026. The version goes up whenever the word table changes.
- Version 2, 11 November 2026: paint, and the words that read the resident's own home: coins, house, storage, materials and world-time. A form that only works something out answers its value: (+ 2 3) answers 5.
- Version 1, 11 November 2026: The word table: the home's words that change the house (roof, floor, window-box, room, build-up, hang-lights, porch, chimney, the house's shape, place and move), defobject for a toy, defdance for a dance, design for a pixel design, and the language's own names, tests, sums, text, lists, maps and functions. A toy's own words: say, put!, state, refuse and its maker's colours.