Tick feels like a natural conversation between objects. It combines the pure message passing of Smalltalk-80 with the command-token clarity of Tcl.
Every statement is a receiver, a keyword, or an argument—with zero decorative prepositions and zero punctuation noise. Featuring Ruby-style fluent pipelines (|), comma cascades (,), stackless Protothreads coroutines, and native FFI (@).
Compile and run Tick code directly in your browser with zero installation.
Designed as an embeddable, featherweight scripting language for rapid prototyping.
Everything is an object, from integers and booleans to block closures. Objects communicate strictly via unary, binary, or keyword messages without primitive exceptions.
No semicolons, no trailing periods, no parenthesis soup. Newlines terminate statements, and inline expressions nest naturally using Tcl-style brackets [...].
Chain outputs seamlessly with the pipe (|) like modern Ruby or Elixir, and send sequential messages to the same receiver with comma cascades (,).
First-class cooperative coroutines with two-way value exchange. Implemented via Adam Dunkels' stackless protothreads in C and Goroutine channels in Go.
Variables and functions with the @ sigil directly invoke host C functions, system calls, and dynamic DLLs without writing glue code.
Complete, independent reference implementations in C99 and Golang with identical semantics, plus a WebAssembly build for in-browser execution.
Rooted in the timeless object messaging philosophy of Alan Kay and Smalltalk-80.
There are zero unboxed primitive types. Numbers, strings, booleans, code blocks ({ ... }), and classes themselves are first-class objects inheriting from Object. Arithmetic and conditionals are message sends!
Classes are first-class runtime objects (instances of Metaclass). Create classes and subclasses dynamically using Superclass subclass Name vars { ivar1 ivar2 }.
Instance variables are private to each instance and protected from external access. All state mutation uses the clean keyword set (e.g. set balance [balance + amount]). All external interactions are mediated through messages.
Method resolution is late-bound at runtime. Diverse classes can implement common selectors (e.g. speak, area), and the runtime dispatches to the correct receiver implementation.
Every method implicitly returns self if not terminated by return, enabling natural Smalltalk cascading where multiple messages are chained on one receiver with commas (,).
Any class—including core built-ins like integer, string, or Array—can be reopened and extended with custom methods at runtime.
# 1. Base Class with Instance Variables
Object subclass Animal vars { name sound }
Animal method init nameVal sound soundVal {
set name nameVal
set sound soundVal
}
Animal method getName { return name }
Animal method speak {
"$name says: $sound" println
}
# 2. Subclassing & Method Overriding (Inheritance)
Animal subclass Dog vars { breed }
Dog method initDog nameVal breed breedVal {
set name nameVal
set sound "Woof!"
set breed breedVal
}
Dog method speak {
"$name the $breed barks: $sound" println
}
# 3. Cascading Instantiation & Polymorphism
set dog [Dog new , initDog "Rover" breed "Collie"]
dog speak # => Rover the Collie barks: Woof!
# 4. Open Classes (Extend built-ins)
integer method square {
return [self * self]
}
"5 squared = [5 square]" println # => 25
Familiar Smalltalk semantics with a streamlined, modern command-token grammar.
| Feature | Standard Smalltalk | Tick |
|---|---|---|
| Assignment | total := 0. |
set total 0 |
| Unary Message | server start. |
server start |
| Keyword Message | canvas draw: shape at: origin. |
canvas draw shape at origin |
| Sub-expression | x := a + (b factorial). |
set x [a + [b factorial]] |
| Zero-Arg Block | [ self alert ] |
{ self alert } |
| Parameterized Block | [ :x :y | x + y ] |
{ x y | x + y } |
| Fluent Pipeline | ((items select: [:x | x valid]) collect: [:x | x name]) sorted. |
items select { x | x valid } | collect { x | x name } | sorted |
| Message Cascade | pen up; color: "blue"; down. |
pen up, color "blue", down |
| Class Definition | Object subclass: #Dog instanceVariableNames: 'breed' |
Object subclass Dog vars { breed } |
| Method Definition | Dog >> speak [ ^ 'Woof!' ] |
Dog method speak { return "Woof!" } |
| Implicit Self Return | deposit: amt [ balance := balance + amt. ^self ] |
Account method deposit amt { set balance [balance + amt] } |