Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Appendix A: Quick Reference

All of Quill on one page.

-- A comment
--- A doc comment
--- example: 1 + 1 == 2

name = "Amina"                  -- a value that can't change
price = 12.50                   -- numbers are exact decimals
in_stock = true                 -- true or false

var total = 0                   -- a value that can change
set total = total + price * 2   -- change it

say "Hi {name}, total {total}"  -- {} puts a value inside text
say """She said "hi"."""        -- three quotes: no backslash needed
say uppercase trim "  amina  "  -- tidy text: trim, uppercase, lowercase
say length of name              -- how many letters
say name starts with "Am"       -- also contains, ends with
say replace "a" with "4" in name
say join split "a,b,c" by "," with " / "

when
  total > 100 -> say "Free delivery"
  total > 20  -> say "Delivery: 5"
  else        -> say "Delivery: 10"

check total == 25.00            -- a test

size = when                     -- a when that gives a value
  total > 20 -> "big"
  else       -> "small"
say size

for i in 1..3                   -- 1, then 2, then 3
  say i

hobbies = list "coding", "reading"
say hobbies at 1

address = record city = "Anytown"
say address.city

fn double(n: number) -> number
  return n * 2
say double(21)

fn half(n: number) -> number
  require n >= 0                -- what the caller must pass
  ensure result <= n            -- what half promises to give back
  return n / 2
say half(21)

fn book(guests: number where 1..500) -> text   -- 1 through 500
  return "{guests} guests"
say book(120)

type Act                        -- every Act has these fields
  name: text
  fee: USD where 1 USD..500000 USD

act = Act name = "Brass", fee = 150000 USD
roster = list act
say sum fee of roster
say get fee of roster
say get name of roster where fee > 100000 USD   -- only some records
say count of roster                             -- how many
say average fee of roster                       -- the typical amount
say get name of roster sorted by highest fee    -- in order, highest first
say split 100 USD into 3                        -- no cent lost
say round 10.125 USD to cents                   -- half to even
say 20% of 500 USD
say convert 100 USD to EUR at 0.92              -- the rate is written

up = record place = "Up Station", acts = list "Bamenda Brass"
old = record place = "Old Town", acts = list "Market Drums"
desk = record bookings = list up, old
say get place of desk.bookings
Hi Amina, total 25.00
She said "hi".
AMINA
5
true
Amin4
a / b / c
Delivery: 5
big
1
2
3
coding
Anytown
42
10.5
120 guests
150000 USD
150000 USD
Brass
1
150000 USD
Brass
33.34 USD, 33.33 USD, 33.33 USD
10.12 USD
100 USD
92 EUR
Up Station, Old Town

Kinds of values

KindExamples
Text"Hello", "Hi {name}", """He said "hi"."""
Number42, 0.10, -3.5
true/falsetrue, false, total > 10
listlist "coding", "reading", hobbies at 1
recordrecord city = "Anytown", address.city

Operators, tightest first

OperatorsMeaning
( )brackets
-xnegative
* / %multiply, divide, remainder
+ -add, subtract (numbers only)
== != < <= > >=compare
notnot
andboth
oreither

Escapes inside text

\n new line · \t tab · \" quote · \\ backslash · \{ \} braces

Blocks (when, for, fn, record) are indented by exactly 2 spaces.

Reserved words

say check var set when else for in list record of at get sum with fn return maybe found missing fails fail on try require ensure where type round split convert bring permit as ask route respond true false and or not

fn double(n: number) -> number names a calculation. return n * 2 is the value the call becomes, and double(21) calls it. Leave off -> when the function only does work, and call it on its own line. Each parameter has its own kind (text, number, true/false, a currency such as USD, maybe one of those, or list of one of those). The kind after -> is the only kind return may give back.

100 USD + 50 USD is money. Two currencies cannot be added. -> maybe number might be found or missing, and when has to handle both. fails Declined names a failure, fail Declined leaves with it, and the caller writes on Declined or try. on Declined -> say "..." runs and stops; on Declined -> "declined" uses that value and carries on. require says what has to be true when a function is called, and ensure says what is true when it gives back; result is the value it gives back. guests: number where 1..500 gives a parameter its range, ends included. round total to cents rounds half to even (round up/round down choose a side); split 100 USD into 3 and split fee by list 70, 30 never lose a cent; 20% of fee takes a percent; convert 100 USD to EUR at 0.92 changes currency at the rate you write. bring billing uses the functions and types in billing.quill, next to the file. permit read "config" (also write, net, env) says what the program may touch; read_file, write_file, file_exists and env need it. body as Booking reads JSON as a type and fails with Invalid when it doesn’t fit; json(value) writes JSON. bring http adds fetch(url), post(url, body) and send(method, url, body, headers); each gives back status and body, needs permit net, and fails with NetworkDown. bring ai adds ask "question" (text) and ask "question" as Review (checked against the type); it fails with ModelFailed (and Invalid with as), and permit env "ANTHROPIC_API_KEY" or "OPENAI_API_KEY" chooses the provider. bring web adds route GET "/path/{name}" and respond 200, value (text as is, anything else as JSON); quill run serves on PORT (8080). type Act names the fields every Act has; Act name = ..., fee = ... makes one, with every field and its rules checked.

trim, uppercase, and lowercase tidy text. length of name counts its letters. name contains "Dr", starts with, and ends with are true or false, and hobbies contains "coding" looks in a list. replace "-" with " " in code changes every -. split line by "," cuts text into a list, and join names with ", " puts it back together. None of these words is reserved.

at picks one list item: hobbies at 1 reads the first, and set hobbies at 2 = "writing" changes that one item. of is required only for an empty list: list of text, list of number, or list of true/false. A list that already has items leaves of out.

sum fee of roster adds the fee of each record. get fee of roster takes that field as a list. get place of desk.bookings reads a field of a list on a record, and get gpa of school.acceptances reads a field of a nested record. Give that record a name before the dot: first = desk.bookings at 1, then first.place. get bookings with acts in desk is the longer form: it names the list and the field embedded in it. roster where fee > 100000 USD keeps the records whose condition is true; inside it, a field is read by its name, and it works after get ... of and sum ... of. count of roster is how many records there are. average fee of roster is the sum divided by how many, with money rounded to cents. roster sorted by fee puts the lowest first, and sorted by highest fee the highest. count, average, and sorted are words only in those places, so they stay free as names. A missing amount is left out. for stays when each record needs its own step.

Commands

CommandWhat it does
quill run FILE.quillrun a program
quill check FILE.quillfind mistakes without running
quill testrun every test in this folder
quill test shoprun the tests in the folder shop
quill explain FILE.quill:Nshow how Quill read line N
quill new NAMEstart a project; a menu offers the templates
quill new NAME TEMPLATEstart one from a template: app, learn, starter, backend, integration, webhook, ai, ai-backend, finance, banking, automation, library
quill tokens FILE.quillshow the pieces Quill read
quill updatechoose a version of Quill to install (also quill upgrade)
quill update VERSIONinstall that version, or latest
quill helpshow help
quill versionshow the version