Skip to content

This site describes solve-engine as it is on main: 2.43.0, which npm does not have yet. npm installs 2.40.0, so a page may show an answer that version does not give yet.

Conditionals

Package: CONDITIONALS_PACKAGE. Registered by createEngine(); for a slimmer engine, register it explicitly (see choosing packages).

A comparison asks whether one value is bigger than, smaller than or equal to another, and answers true or false. > is greater than, < less than, >= and <= add “or equal to”, == asks whether the two are equal and != whether they differ.

5 > 3 // true
10 == 10 // true
3 != 4 // true
5 >= 5 // true

A boolean is a value that is either true or false, the kind of answer a comparison gives. and is true only when both sides are true; or is true when at least one is. They are how two conditions are combined into one.

true and false // false
true or false // true

Negating a condition turns it around: not makes true false and false true. It is how a note says “unless”, or asks that something does not hold. The word not and a ! in front of a value mean the same thing.

not true // false
not (1 > 2) // true
!(1 > 2) // true
!false // true

The two spellings bind differently, each the way it does in the languages it comes from. not takes the whole comparison after it, as it does in Python and SQL, so not 1 > 2 asks whether 1 is not more than 2; it stops at and and or, so not true and false is (not true) and false. A ! takes only the one value right after it, as it does in C and JavaScript, so a comparison after it needs its brackets: !(1 > 2).

not 1 > 2 // true
not true and false // false
if not 5 > 3 then 1 else 2 // 2

Negation is defined for true and false only. A number is not read as “zero means false”, and a ! in front of one is not a bit flip (that is ~, see bitwise operators), so negating anything that is not a boolean is refused by name, with the comparison to write instead:

not 5 // "not" works on true or false, and 5 is a number: compare it first, as in not (x > 3).
!1 > 2 // "!" works on true or false, and 1 is a number: compare it first, as in not (x > 3).

A list of answers, a row of true and false in square brackets, is negated one answer at a time, whether it is written out, worked out from comparisons, or held in a name. A list of numbers is not a list of answers, so not before one is refused in the same words as not 5:

not [true, false] // [false, true]
not [1 > 0, 2 > 3] // [false, true]
not [1, 2] // "not" works on true or false, and [1, 2] is a list: compare it first, as in not (x > 3).
![1, 2] // "!" works on true or false, and [1, 2] is a list: compare it first, as in not (x > 3).

not [1, 2] used to be read as an item of a list called not, and answered “Undefined variable: not”, while ![1, 2] and not ([1, 2] > 1) were read as negation.

The boundary: a ! straight after a value is still the factorial (5! is 120), and != is still “is not equal to”. not is ordinary English, so it is read as negation only where a value is expected (at the start of a line, or after if, then, else, a bracket, and, or or a comparison) and a condition follows it. A sentence that starts with it (not now) stays prose, and a variable called not keeps working, except before a square bracket, which opens a list to negate, so an item of a list called not is not read as not[0]:

not = 3 // 3
not + 1 // 4

Text is anything in quotes, such as "255" or "paid". Two pieces of text are equal when they are the same characters. Text and a number are two kinds of thing, even when they read alike, so == between them is false and != is true. To compare the number a piece of text holds, turn it into a number first with as number:

"paid" == "paid" // true
255 == "255" // false
255 != "255" // true
"255" as number == 255 // true

Text has no order that a note would mean (is "apple" less than "pear"?), so <, <=, > and >= with text on either side are refused by name, and the message points at as number when the text holds a number:

"5" > 3 // "5" on the left is text and the other side is a number, so they cannot be put in order. To read the text as a number, write "5" as number.
"a" < "b" // Text has no order: two pieces of text can only be compared with == or !=, not <.

The boundary: == gives an answer rather than a refusal, as it does for a length beside a mass (1 m == 1 kg is false), so a condition such as if x == "yes" still works whatever x holds. A check is stricter, and refuses a check between text and a number, since a check that cannot hold is a mistake in the note. Earlier versions read the text as a number, or as 0 when it was not one, so "abc" == 0 was true.

A list (a row of numbers in square brackets) is compared one element at a time, so the answer is a list of true and false, one per element, and and, or and not combine such lists element by element. Comparing a list has the details.

[100, 200] > 150 // [false, true]
[100, 200] > 150 and true // [false, true]

The boundary: an if needs one answer, so a list as its condition is refused by name rather than read as false.

if [100, 200] > 150 then 1 else 0 // "if" needs one true or false, and this is a list of 2 cells. Compare one cell, as in v[0] > 5, or choose for each cell with map, as in map(if x > 5 then 1 else 0, v).

A conditional expression picks one of two values depending on a condition: if the condition, then the value to use when it holds, else the value when it does not. It is how a note gives a different answer in different cases, such as a charge that applies only above some amount.

if 5 > 3 then 100 else 200 // 100

Programming languages often write the same choice with a question mark and a colon, condition ? value : other (the “ternary” operator). The engine has no such operator, and a colon on a line usually ends a label, so rather than read the text before the colon as a name and answer with the last value, the line is refused with its own parts spelled the way the engine reads them:

true ? 25 : 30 // ERROR: There is no choice written with "?" and ":": write if true then 25 else 30
if true then 25 else 30 // 25

A conversion changes how a value is shown or which unit it is in: as hex, in binary, in m. Written on either side of a comparison, it belongs to that side, so the comparison is made between the two converted values and the line reads the way it is said:

255 in hex == 0xff in hex // true
5 km in m == 5000 m // true
0xff in hex != 255 in binary // false

The boundary: a conversion written after the right-hand side is that side’s, not the comparison’s. To convert the true or false a comparison answers, put the comparison in brackets:

5 > 3 as number // true
(5 > 3) as number // 1

A check line states a comparison the note must keep true, and becomes an error naming both sides when it stops holding; it has its own page, checks.

A line that joins two comparisons with and asks whether both hold. Each comparison is worked out first and and then combines the two answers, so the line reads the way it is said, with no brackets needed. The symbol form && groups the same way.

10 >= 5 and 3 > 1 // true
10 >= 5 and 3 > 4 // false
10 >= 5 && 3 > 1 // true

It works the same with variables, which is where the form is usually met:

x = 10
y = 5
x >= y and y > 1 // true
x >= y and y > 7 // false

and is also the word form of addition, so between two plain numbers it adds:

2 and 3 // 5

The boundary: and means “both are true” only when both sides are true or false answers. With a number on one side and a comparison on the other it is still an addition, counting true as 1 and false as 0, so 2 and 3 > 1 is 2 + 1. Brackets make the intended reading explicit:

2 and 3 > 1 // 3
(2 and 3) > 1 // true