Guide · 08 of 09
Loops & Logic
Prism has compile-time loops and conditionals that unroll before the scene is built. They use brace blocks, same as everything else. Generates static objects — the scene structure is always fixed at runtime.
for#
Unrolls at compile time. The loop variable is a compile-time constant inside the block. Use f"id{i}" to give each object a unique id.
for <var> in range(start, end[, step]) { ... }
Example
if#
Compile-time conditional. Useful for color-by-sign or emitting different objects based on loop variables.
if <cond> { ... } [elif <cond> { ... }] [else { ... }]
Example
repeat#
Expands at render time, not compile time — <count> can be a state expression (e.g. a slider), so the number of instances updates live as the learner drags it. The range must start at 0. Inside the body, <var> is a live runtime value (0..count-1), usable in any expression alongside real state. Each body object's id gets #<i> appended automatically, so plain ids are fine (no f-string needed). Capped at 500 instances.
repeat <var> in range(0, <count>) { ... }
Example
reveal#
Objects inside stay hidden until the slide's exercise has been checked, then appear — the predict-then-reveal pattern (sketch/guess first, see the real answer after). Any normal object statement is allowed inside; a slide needs an exercise for the reveal to ever trigger.
reveal { ...objects... }
Example
let#
Assigns a compile-time constant. Can reference other let values and loop variables. Not a runtime state variable.
let <name> = <expr>
Example
def#
Defines a reusable macro. Call it like a function — arguments are substituted as compile-time values. Declared inside a scene, it's callable only in that scene. Declared at the top of a lesson (alongside its slides), it's callable from every slide's scene in that lesson.
def <name>(param1, param2, ...) { ... }
Example