Cirru Syntax Essentials

1. Indentation = Nesting

Cirru uses 2-space indentation to represent nested structures:

defn add (a b)
  &+ a b

Equivalent JSON:

["defn", "add", ["a", "b"], ["&+", "a", "b"]]

2. The $ Operator (Single-Child Expand)

$ creates a single nested expression on the same line:

; Without $: explicit nesting
let
    x 1
  println x

; With $: inline nesting
let (x 1)
  println x

; Multiple $ chain right-to-left
println $ str $ &+ 1 2
; Equivalent to: (println (str (&+ 1 2)))

Rule: a $ b c["a", ["b", "c"]]

3. The | Prefix (String Literals)

| marks a string literal:

println |hello
println |hello-world
println "|hello world with spaces"
  • |hello"hello" (string, not symbol)
  • Without |: hello is a symbol/identifier
  • For strings with spaces: "|hello world"

4. The , Operator (Expression Terminator)

, forces the end of current expression, starting a new sibling:

; Without comma - ambiguous
if true 1 2

; With comma - clear structure
if true
  , 1
  , 2

Useful in cond, case, let bindings:

cond
    &< x 0
    , |negative      ; comma separates condition from result
  (&= x 0) |zero
  true |positive

5. Quasiquote, Unquote, Unquote-Splicing

For macros:

  • quasiquote or backtick: template
  • ~ (unquote): insert evaluated value
  • ~@ (unquote-splicing): splice list contents
defmacro when-not (cond & body)
  quasiquote $ if (not ~cond)
    do ~@body

JSON equivalent:

[
  "defmacro",
  "when-not",
  ["cond", "&", "body"],
  ["quasiquote", ["if", ["not", "~cond"], ["do", "~@body"]]]
]

6. Common Patterns

Function Definition

defn function-name (arg1 arg2)
  body-expression

Let Binding

let
    x 1
    y $ &+ x 2
  &* x y

Conditional

if condition
  then-branch
  else-branch

Multi-branch Cond

cond
  (test1) result1
  (test2) result2
  true default-result

JSON Format Rules

When using -j or --json-input:

  1. Everything is arrays or strings: ["defn", "name", ["args"], ["body"]]
  2. Numbers as strings: ["&+", "1", "2"] not ["&+", 1, 2]
  3. Preserve prefixes: "|string", "~var", "~@list"
  4. No objects: JSON {} cannot be converted to Cirru

Common Mistakes

❌ Wrong✅ CorrectReason
println helloprintln \|helloMissing \| for string
$ a b c at line starta b cA line is an expression, no need of $ for extra nesting
a$ba $ bMissing space around $
["&+", 1, 2]["&+", "1", "2"]Numbers in syntax tree must be strings in JSON
Tabs for indent2 spacesCirru requires spaces