Chapters

Catena expressions and operators

An expression is a piece of Catena that computes a value. 2 + 2 is an expression; so is price × 1.2, age ≥ 18, and 90 km ÷ 1.5 h. Every sequence you write is built from expressions: they set values, decide which branch a condition takes, and produce the results your steps return. This chapter teaches how expressions are put together — the operators you combine values with, the order those operators apply in, and the rule that grouping is always written out by hand. It then shows how the same operators work not just on plain numbers but on money and on measured quantities that carry units.

You do not need to have read any other chapter first, but it helps to know what the values themselves are. Numbers, text, money, and quantities are described in Types and formatting; the one container that holds a collection of values is the Bag, covered in Bags.


Building an expression

An expression combines values with operators. A value is a literal you write down (5, 3.14, "hello", 20 kg) or the name of something you defined earlier. An operator is a symbol that acts on values: + adds two numbers, < compares them, AND combines two yes/no answers. Operators come in two shapes:

  • Binary operators sit between two values: a + b, x ≤ y.
  • Unary operators sit before a single value: the minus sign in -b negates it; NOT in NOT ready flips a yes/no answer.

Expressions nest. The result of one operator becomes an input to the next, so 2 + 3 × 4 is a single expression built from two operators, and (-b + r) / (2 × a) is built from several. The rest of this chapter is about the operators available and the rules that decide how a nested expression is read.


Arithmetic operators

These are the everyday calculation operators. Several have an alternate spelling — a plain-keyboard form you can type when the mathematical symbol is inconvenient. Both forms mean exactly the same thing.

Operator Meaning Alternate spelling
+ addition
- subtraction, and unary minus (negation)
× multiplication *
÷ division /
^ power (raise to an exponent) x^y
square root SQRT

So 6 × 7 and 6 * 7 are the same expression, as are 10 ÷ 4 and 10 / 4, and √9 and SQRT 9. Use whichever reads more clearly in the sequence you are writing.

3 + 4 × 2        # 11  — multiplication happens before addition
2 ^ 10           # 1024144            # 12
-5 + 3           # -2  — the leading minus is unary negation

Working on a whole Bag at once. When one side of an arithmetic operator is a Bag (a collection), the operation is applied to every item. [1, 2, 3] + 1 gives [2, 3, 4], and [10, 20, 30] ÷ 10 gives [1, 2, 3]. This lets you transform a whole set of values without writing a loop. The details of Bags — how you build and read them — are in Bags.


Precedence, and why you always write the brackets

When an expression mixes operators, Catena needs a rule for which one acts first. That rule is precedence, and it matches ordinary school mathematics:

  1. ^ (power) is applied first.
  2. × and ÷ next.
  3. + and - last.

Operators of the same level are read left to right (left-associative), with one exception: ^ is read right to left (right-associative), so 2 ^ 3 ^ 2 means 2 ^ (3 ^ 2), which is 2 ^ 9, not (2 ^ 3) ^ 2.

2 + 3 × 4        # 14, not 20  — × before +
2 ^ 3 ^ 2        # 512  — powers group from the right: 2 ^ (3 ^ 2)

Grouping is never optional. When you want a different order from the default, you group with parentheses ( ) — and Catena expects you to write them whenever grouping matters, rather than leaning on a precedence rule you might misremember. Catena does not silently infer grouping for you. The quadratic formula's numerator and denominator, for example, must each be bracketed as you intend:

(-b + r) ÷ (2 × a)      # each group written explicitly

Without the brackets, -b + r ÷ 2 × a would divide r by 2 and multiply by a before adding — almost certainly not what you meant. Writing the parentheses is the reliable way to say precisely what you want, and it makes the sequence readable to whoever opens it next. When in doubt, bracket it.

( ) groups; it never makes a Bag. Parentheses do one job only: they group a sub-expression so it is evaluated as a unit. (5) is simply the number 5. A collection of values is written with square brackets [ ] instead — [5] is a one-item Bag, a different kind of thing entirely. Keeping the two apart removes a common ambiguity: round brackets never build a container, and square brackets always do. See Bags for what square brackets construct.


Comparison operators

A comparison asks a yes/no question about two values and answers with a Boolean — a true/false result. These are the operators you put in a condition to decide which way a sequence branches.

Operator Question it asks Alternate spelling
= are the two values equal?
are they not equal? <>
< is the left less than the right?
> is the left greater than the right?
is the left less than or equal? <=
is the left greater than or equal? >=
age18         # true if age is 18 or more
total0        # true unless total is exactly zero
score <= 100     # the plain-keyboard form of score ≤ 100

= compares; it does not assign. In Catena, = always means "is equal to," the same as in school mathematics. It never stores a value. Assignment — giving a name a value — is written with the arrow -> instead, so the two jobs never collide. x = 5 is a question ("is x equal to 5?"); storing five into x is 5 -> x. Because assignment has its own symbol, you can use = freely for equality wherever a comparison is wanted.


Boolean logic

A Boolean is a value that is either true or false. Comparisons produce Booleans, and the Boolean operators combine or invert them so you can express a compound condition:

  • AND is true only when both sides are true.
  • OR is true when either side (or both) is true.
  • NOT flips a single Boolean: NOT true is false.
age18 AND age < 65      # true for an adult under 65
day = "Sat" OR day = "Sun" # true at the weekend
NOT (balance < 0)          # true when the balance is not negative

A comparison naturally feeds a Boolean operator: each comparison yields true or false, and AND / OR combine those answers. Group the parts with parentheses whenever the reading could be unclear — the same rule as for arithmetic. These operators are what conditions in Control flow are built from.

When your real goal is to pick out the matching items from a collection rather than test a single condition, Catena offers a dedicated query form for that, which reads more naturally than stringing Booleans together by hand; see Bags.


Numbers, money, and quantities

The operators above are not limited to plain numbers. Catena values can carry a unit20 kg, 90 km, 1.5 h, $100, €20 — and arithmetic understands those units and checks them.

Compatible units combine and convert automatically. Adding two masses works even when they are written in different units; the result comes back in a sensible unit:

5 kg + 200 g               # 5.2 kg  — grams folded into kilograms
90 km ÷ 1.5 h              # 60 km/h — dividing distance by time gives a speed

Dividing one dimension by another produces the combined unit you would expect (distance over time is a speed), exactly as it does when you work it out on paper.

Mixing incompatible units is an error. You cannot add a mass to a length — the two measure different things, and the result would be meaningless. Catena refuses it rather than returning a wrong number, and points out the mismatch:

5 kg + 3 m                 # ERROR — a mass and a length cannot be added

This is deliberate protection: a units error caught as you write the sequence is far better than a silently wrong figure later.

Currency needs a conversion rate. Money is treated as a unit too, so a single currency behaves just like any other quantity: $100 + $20 is $120. Adding two different currencies, though, is only possible if the sequence knows the exchange rate between them — and that rate has to come from somewhere current, because rates move. If no rate is available, the addition is an error:

$100 + $20                 # $120  — same currency, always fine
$100 +20                 # ERROR unless a conversion rate is in scope

To make cross-currency arithmetic work, the sequence must have a rate provider available. How a sequence obtains live rates through a connector is covered in Connectors and the API. The formatting of money and quantities — how many decimal places, which symbol — is in Types and formatting.


Worked examples

Example 1 — precedence and explicit grouping. Suppose b is 6, r is 4, and a is 1, and you want (-b + r) ÷ (2 × a).

6 -> b
4 -> r
1 -> a
(-b + r) ÷ (2 × a)         # (-6 + 4) ÷ (2 × 1) = -2 ÷ 2 = -1

The two bracketed groups are each worked out first, then divided. Remove the brackets and the default precedence would compute something else entirely — which is why the grouping is written out.

Example 2 — a comparison inside a Boolean condition. A ticket is discounted for children and for seniors. With age set, the eligibility test combines two comparisons with OR:

age < 13 OR age65       # true for a child under 13 or a senior 65+

Each comparison returns true or false on its own; OR reports true if either one is true. This is the kind of expression you would place in a condition to choose the discounted branch — see Control flow.

Example 3 — arithmetic with units. A trip of 90 kilometres takes an hour and a half. The average speed is distance divided by time:

90 km ÷ 1.5 h              # 60 km/h

The units divide along with the numbers, so the answer arrives already labelled as a speed. Had you written 90 km ÷ 1.5 kg instead, Catena would report a units error, because kilometres and kilograms do not combine into anything meaningful.


See also

  • Types and formatting — the values operators act on: numbers, text, money, and quantities, and how they display.
  • Bags — the one container, square-bracket construction, element-wise arithmetic, and the query form for selecting items.
  • Control flow — using comparisons and Boolean expressions in conditions to steer a sequence.
  • Connectors and the API — how a sequence obtains live exchange rates so cross-currency arithmetic can work.