kapy academy

Expressions

8 min readUpdated Aug 2026

Every numeric field in the editor is an expression field. Click the value and you get a small code editor instead of a number box, so a depth can read PLATE_T * 2, a hole can read SHAFT + HOLE_COMP, and a count can read round(LENGTH / PITCH).

A dimension holding a parameter rather than a number. Any numeric field takes the same thing.
A dimension holding a parameter rather than a number. Any numeric field takes the same thing.

The field editor

Click the value to open it. Type. Three ways out:

  • Enter commits the expression and confirms the panel, so the step closes as well.
  • Esc reverts the field to what it held before.
  • Clicking away commits.

While you type anything that is not a plain number, a grey = <result> appears at the end of the line and updates live, so you see the millimetres the formula produces before you commit. Mistakes are underlined as you type: a formula that cannot be parsed is marked as an error, one that parses but cannot be evaluated as a warning.

Newlines are stripped from anything you paste, so a formula copied out of a spreadsheet arrives on one line.

Once committed and the panel is closed, a field holding a formula shows a small grey fx badge instead of the formula. A field whose formula is broken shows a red !, with the message as its tooltip.

Autocomplete

Ctrl+Space opens the list, and so does typing the first letters of a name. Each completion shows what it currently evaluates to, = 12.5 mm, so you can pick between two similar names without leaving the field.

Type @ to list parameters only. The general list also carries functions and constants, and @ is faster when you know you want a parameter.

Creating a parameter without leaving the field

Type a name that does not exist yet and accept the completion. The editor inserts NAME(0) with the 0 selected, so you type the default straight over it. On commit, a real parameter is created with that value, and the field is left holding the bare name.

Typing NAME(12) by hand does the same thing. This is the shortest route from "this number should have a name" to a named parameter, and it is the only way to create a parameter whose unit is not millimetres: a parameter minted inside a field inherits that field's unit, while one created from the Parameters window is always mm.

What you can write

Accepted syntax
Kind What is accepted
Arithmetic + - * / % ^, and unary + -
Comparison == != < > <= >=
Logic and or not xor
Conditional cond ? a : b
Grouping Parentheses
Functions sqrt abs min max floor ceil round sin cos tan if
Constants pi, true, false, and the calibration constants
Text Only as the operand of == or != against a Preset parameter

The C-style logical operators are accepted as well: && for and, || for or, ! for not.

That function list is the whole list. There is no log, no atan, no clamp. Names are read without regard to case, and identifiers are stored in upper case.

if and the ? : form do the same job, so if(TALL, 40, 25) and TALL ? 40 : 25 are the same expression. Either one is how a boolean parameter reaches a numeric field.

Two operators are worth reading twice. ^ raises to a power: 2^10 is 1024. And % gives what is left over after a division, on decimals as well as whole numbers, so 7.5 % 2 is 1.5 and LENGTH % PITCH is the offcut at the end of a row of ribs. Its sign follows the number you divide by, not the one in front: -7 % 3 is 2, not -1.

Calibration constants

The uppercase constants HOLE_COMP, PIN_COMP, and the FIT_ and MIN_ families read live from the active print setup. They are not fixed numbers stored in the document.

This is what makes a printed fit portable. A hole written as SHAFT_DIA + HOLE_COMP carries the intent, "clearance for a shaft of this size on this printer", rather than a number you measured once on a machine you may not still own. Change the print setup and the hole changes with it.

Their names are reserved, so you cannot create a parameter that shadows one.

What a rename does to a formula

A formula holds the name as text. Renaming a parameter never rewrites the expressions that mention it, so every formula that named the old one still says the old word, and every one of them goes stale the moment you press Enter on the new name. Nothing is offered, nothing is rewritten, and no count of what just broke appears.

You find out in two places. A parameter row whose own value is such a formula turns amber, reports expression references an unknown parameter, and keeps the last value it managed to compute, which is the value from before the rename. A feature field in the same position shows a red ! badge with Unknown parameter '{NAME}' as its tooltip, and the step that owns it fails.

The model does not fall over, which is the trap: an amber row still hands out a number, so a part can go on looking right while one of its dimensions is frozen at whatever it was before the rename.

After a rename, walk the Parameters window for amber rows and open every step that used the old name in a formula. Fields bound through the picker, with no formula, need nothing: those follow the rename on their own. Better still, name a parameter well enough the first time that you never rename it.

Refusals

Each of these appears against the field, and the wording is the whole diagnosis.

Syntax the parser will not take:

  • Expression is empty
  • Unsupported syntax: assignments are not allowed, which also covers function definitions, property access, arrays, objects, ranges and more than one statement
  • Unsupported operator: {op}
  • Unknown function '{name}'

A name that does not resolve:

  • Unknown parameter '{NAME}'
  • Circular dependency detected: A → B → A, when two parameters end up defined in terms of each other

A value of the wrong shape:

  • Expression returned boolean, expected number, and its mirror Expression returned number, expected boolean
  • Expression did not evaluate to a finite number or boolean, which is what a division by zero produces
  • Text values are only allowed in == / != comparisons
  • '{NAME}' is not an enum parameter — it can't be compared to text
  • '{value}' is not an option of '{NAME}' (options: …)

When it goes wrong

The field reverted and said nothing. This is the one to know about. A committed expression that fails to parse is discarded without a message and the field goes back to its previous value. If a formula you typed is not there afterwards, it did not parse. Retype it and watch the underline before you commit.

A field shows a red !. The formula parses but no longer evaluates, and the cause is a parameter it names being renamed or deleted. Hover the badge for the message, then open the field and fix the name.

A preset parameter is not in the autocomplete list. Preset parameters are left out of the suggestions, even though comparing one is legal. Type the name yourself: MODE == "wide" works.

A text parameter will not go into a calculation. Text can only be compared with == or != against a Preset parameter. It can never take part in arithmetic. If you want a text value to change a dimension, make it a Preset instead and compare against it, or drive the dimension from the preset's assignments.

The step closed when you pressed Enter. That is Enter doing both jobs. Reopen the step; the value committed.

See also

Discord