A walkthrough of what makes Turmeric tick.
From algebraic effects to structural union types, each stop in this tour shows you real language features with real code.
01 -- Algebraic Effects
Your functions declare what side effects they may perform. Their callers decide how to handle them -- in production, in tests, or as mocks.
The type system ensures no effect goes unhandled. Swap between handlers at the call site without touching the core logic.
defeffect · perform · handle · resume02 -- Typeclasses
Typeclass dispatch resolves to a concrete instance at compile time -- no virtual tables, no runtime cost. Define a typeclass once and the compiler verifies every call site has a valid instance.
The ^Show constraint syntax expresses type requirements without sacrificing precision or performance.
03 -- ADTs, GADTs & Pattern Matching
defdata declares sum types; defgadt lets each constructor specialize its own type parameters. Every match arm refines what the checker knows -- no casts, no runtime tags.
Missing branches are compile errors, not runtime surprises. Every case is statically verified before your program runs.
defdata · defgadt · match · -Xgadt04 -- Delimited Continuations
Turmeric reifies a slice of the call stack as an ordinary value. reset delimits the region; shift captures it.
Generators, async/await, and backtracking are all built on those two primitives -- no special syntax, no compiler magic.
reset · shift · delimited05 -- Macro System
Macros in Turmeric operate directly on the syntax tree at compile time. New control flow, DSLs, and syntactic sugar are defined with defmacro -- the output is indistinguishable from hand-written code.
Quasiquote (`) and unquote (~) make code templates readable. No runtime overhead, ever.
06 -- Reference Counting
Turmeric uses reference counting with compiler-assisted elision. rc/clone increments; rc/drop decrements. Cleanup is deterministic -- no GC pauses, no dangling pointers.
When the count hits zero, the value is freed right there, at that line. You can see exactly where memory is released.
rc/of · rc/clone · rc/drop · rc/strong-count07 -- Higher-Order Functions
Functions are first-class values in Turmeric -- pass them, return them, store them, compose them. Closures capture their lexical environment with full type inference.
The standard library's map, filter, and reduce work uniformly over any foldable structure, not just lists.
08 -- Sweet-Exp Syntax
A single #lang declaration switches from Lisp-style parentheses to Sweet-Exp notation -- indentation-sensitive, with f(args) for inline calls and $ to avoid extra nesting.
Both syntaxes compile to the same AST. Sweet-Exp code and classic Turmeric code share libraries freely and can coexist in the same project.
#lang turmeric/neoteric · f(args)09 -- Contract Types
{ x : T | p } is a contract type -- a value of type T that satisfies predicate p, checked automatically at every call site. Name them with deftype or write them inline in any parameter or return position.
Declare invariants once in the signature with :pre and :post. The compiler inserts the checks -- you don't have to remember to. Strip them from release builds with no code changes.
10 -- Spice -- Package Manager
One build.tur file describes your package and all its spices -- Turmeric fetches, builds, and links them automatically. Git URLs and version refs are all you need.
C and CMake dependencies go under :cmake-deps and are wired in via CPM -- no manual CMake configuration required.
11 -- Structural Typing
(int | bool) is a structural union -- the compiler generates exhaustiveness-checked dispatch for every member with no boxing or runtime overhead. Every union member must be handled.
The any top type enables gradual typing: every concrete type is a subtype of any. Inspect the tag at runtime with type-of. Enable both with -Xunion-types.
Open the playground and try any of these features right in your browser.