Guide · 13 of 15
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
group#
Moves, turns and scales a set of objects as one thing. Write the children in the group's own coordinates and the compiler rewrites each one's points, so at, rotate and scale can read a param and the whole set follows a slider. A child point p lands at at + origin + scale * R(rotate) * (p - origin): at moves the group, rotate turns it (degrees counter-clockwise), scale grows it, and origin is the pivot the turn and the growth happen about, in the children's coordinates (default (0, 0)). In a space3 scene at and origin are (x, y, z) and rotate is (rx, ry, rz) in degrees, applied about x, then y, then z. Marker sizes, stroke widths and text sizes are pixels and never scale. alpha, show and context go to every child. The group's id works in a step's indicate, focus and surround, and in morph, where it crossfades and nothing moves. group L = ladder(theta, 10) { at: (1, 0) } is the same as a group holding that one def call, and the call's arguments may read params. Groups nest (the inner one applies first) and may hold a repeat, and a repeat may hold a group. Declare params, controls, steps and morphs outside it. A group that moves refuses what can't be rewritten exactly: a draggable point, an area, a gas, a curve with where:, a line given by through:, and a rotated image, highlight or slope.
group <id> { ...objects... } [{ at: (x, y), rotate: <degrees>, scale: <k>, origin: (x, y), alpha: <expr>, show: <expr>, context }] group <id> = <def>(args) [{ ...same props }]
| prop | type | description |
|---|---|---|
| at | (x, y) or (x, y, z) | where the group sits, (x, y) or (x, y, z) |
| rotate | degrees | (rx, ry, rz) | turn, counter-clockwise degrees (three angles in space3) |
| scale | expr | grow or shrink about origin |
| origin | (x, y) or (x, y, z) | the pivot for rotate and scale, in the children's coordinates (default (0, 0)) |
| alpha | expr | fades every child, multiplied into its own |
| show | expr | every child shows only while this holds |
| context | flag | every child becomes backdrop |
Example
morph#
Turns one object into another without losing track of it. As by goes from 0 to 1 the first object fades out and the second fades in, and when both have a position they travel together from the first one's spot to the second's. Drive by with a param that a timeline step animates, and a word can visibly become its symbol right where it was. Any object can also take alpha: <expr> to fade as a whole, where opacity: is only a shape's fill, and any object can take draw: <expr from 0 to 1> to be drawn in progressively: a curve, line, vector or area left to right, a polygon or rect along its edge, a circle or arc sweeping round (a circle from angle 0, counter-clockwise, a rect from its top-left corner), and a point, label or image fading in. In a space3 scene segment3 and polygon3 draw on the same way, and on a numberline a point fades in. Tie draw to a param a timeline step animates and the student builds the picture one press at a time, and can step back through it.
morph <from-id> -> <to-id> { by: <expr from 0 to 1> }
Example
let#
Names a value. Can reference other let values and loop variables. A value that reads state (let a = t * 2) follows the scene, but can't set a for range, an if or an id.
let <name> = <expr>
Example
def#
Defines a reusable macro. Call it like a function: an argument is a number, or an expression that reads the scene's state and follows it live (a live one can't set a for range, an if or an id). 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