Skip to content

math and console

math.pi 3.141592653589793
math.e 2.718281828459045
math.tau 6.283185307179586

These fold to their literal value at compile time, so they cost nothing at runtime:

temp turns: num = math.pi * 2;
motion.forward(10 * math.pi);
math.pow(base: num, exponent: num) -> num

Declared with an empty body and no opcode. It type-checks and produces nothing. The ** operator has the same gap and is worse — it lowers silently to an empty literal, so you get a wrong answer with no error.

Write it out:

proc pow(base: num, exp: num) -> num {
temp result: num = 1;
for (i, exp) {
result = result * base;
}
return result;
}

That covers whole-number exponents, which is most of what a Scratch project needs. For fractional powers, Scratch’s [sqrt v] of () block is the practical route — bind it yourself:

proc mathop(@opcode = "operator_mathop", operator: str, num: num) -> num {}
temp root: num = mathop("sqrt", 16);

No random, min, max, abs, round, floor, or trigonometry. Scratch has blocks for all of these; the stdlib has not wrapped them. Bind the opcodes directly:

proc random(@opcode = "operator_random", from: num, to: num) -> num {}
proc round(@opcode = "operator_round", value: num) -> num {}
temp roll: num = random(1, 6);
console.log(msg: str) -> void
console.warn(msg: str) -> void
console.error(msg: str) -> void
console.input(prompt: str) -> str

For output, say it:

looks.say(f"score is {score}", 1);

Or keep a log list, which persists and is scrollable:

public logLines: list<str> = [];
proc log(msg: str) -> void {
logLines.add(msg);
logLines.show();
}

For input, use the sensing pair that console.input was meant to wrap:

sensing.ask("What is your name?");
temp name: str = sensing.answer();
looks.say(f"Welcome, {name}!", 2);

console.input cannot work until yields procedures are lowered, because it has to both run a blocking block and produce a value — the two-call form does that explicitly.