Trainerflow Docs trainerflow.com
The language › Values

The language

Values

The primitive values Coach understands — numbers, measurements, ranges, strings, booleans and nil — and the operators that work on them.

Expressions in Coach consist of a combination of primitive values (and collections of those) and operations between them. Below we will see what those primitive values are and the operations that can be performed on and between them.

Number

A number is either an integer or a fractional number, similar to what you would type into a pocket calculator.

Example

12
6.33
0.05
-4
3.12e-3 // same as 0.00312

Operators

Numbers support the following operators.

Arithmetic operators always return numbers:

Symbol Name Example Result
+ add 3.4 + 3 6.4
- subtract 3 - 4.44 -1.44
* multiply 2.2 * 4.5 9.9
/ divide 7.84 / 2 3.92
% remainder 44 % 3 2
^ power 2^4 16

Comparison operators always return booleans:

Symbol Name Example Result
== equals 4 == 4 true
!= not equals 4 != 5 true
< less than 2 < 4.333 true
> greater than 6.55 > 6.55 false
<= less than or equals 4.5 <= 4 false
>= greater than or equals 5.34 >= 5.35 false

Numbers compare by amount, however they were written or worked out: 1 == 1.0 and 10 / 4 == 2.5 are both true.

Measurement

A measurement is a number together with a unit of measurement, one that is convertible to the International System of Units. Most of what a training program deals with is a measurement: weights, durations, distances, heart rates.

Units

The unit is written between two vertical bars, right after the number, e.g. |m/s|. It is made of unit symbols combined with any of the operators:

Symbol Name Example
* multiply kg*m
/ divide km/h
^ power kg*m/s^2

Different units may measure the same physical property. Coach performs dimensional analysis under the hood, so it knows that units which measure the same physical property have the same dimensions. This is what makes operations between measurements with different units (but the same dimensions) possible: you can add pounds to kilograms and Coach will do the conversion for you.

The units that Coach recognises are:

Symbol Name Prefix
m metre Yes
ft foot No
in inch No
yd yard No
mi mile No
g gram Yes
lb pound No
oz ounce No
s second Yes
min minute No
h hour No
day day No
K kelvin Yes
C Celsius Yes
F Fahrenheit No
J joule Yes
cal calorie Yes
N newton Yes
dyn dyne No
kp kilopond No
pdl poundal No
lbf pound-force No
W watt Yes
Hz hertz Yes
kph kilometres per hour No
mph miles per hour No
bpm beats per minute No

As you have noticed, some of those units accept a prefix. That is how kg (kilo + gram) and km (kilo + metre) come about. The recognised prefixes are:

Symbol Name Multiplier
Y yotta 1e24
Z zetta 1e21
E exa 1e18
P peta 1e15
T tera 1e12
G giga 1e9
M mega 1e6
k kilo 1e3
h hecto 1e2
da deca 1e1
d deci 1e-1
c centi 1e-2
m milli 1e-3
μ or mu micro 1e-6
n nano 1e-9
p pico 1e-12
f femto 1e-15
a atto 1e-18
z zepto 1e-21
y yocto 1e-24

Example

5.45|kg|
23|kg*m/s^2| // same as 23|N|
12.3e-3|km/h|
67|bpm|

Operators

Measurements support arithmetic between a measurement and a number, or between two measurements, and comparison between measurements with the same dimensions. Arithmetic produces measurements, while comparison produces booleans.

Arithmetic between two measurements works on the number and on the unit alike. When the two units differ, the result is in the unit of the leftmost measurement. Addition and subtraction are only allowed between measurements of the same dimensions; multiplication and division produce a new unit.

Symbol Name Example Result
+ add `2 lb
- subtract `4 N
* multiply `3 kg
/ divide `100 m

Arithmetic between a number and a measurement:

Symbol Name Example Result
* multiply `4 * 1.1 kg
/ divide `1 / 4 N
^ power `2 lb

Adding a plain number to a measurement, as in 2|kg| + 3, is an error: Coach cannot know what unit the 3 is in. Raising a number to a measurement, as in 2^2|kg|, is an error too, because it makes no sense to have a measurement in the exponent.

Comparison is possible if, and only if, the two measurements have the same dimensions. Comparing a weight with a distance produces an error.

Symbol Name Example Result
== equals `1 kg
< less than `2 in
> greater than `3 m/s
<= less than or equals `8 kg
>= greater than or equals `60 bpm

Range

A range represents a stretch of values between two boundaries. It is how a program says “8 to 12 reps” or “anything above 60 kg”. The notation of a simple range is start..end, or start...end when the end itself belongs to the range.

A range accepts numbers, or measurements of the same dimensions, as its boundaries. A range with no start begins at negative infinity, and a range with no end goes on to positive infinity.

Notation Contains
a..b everything above a and below b
a...b everything above a, up to and including b
..b everything below b
...b everything up to and including b
a.. everything above a

Example

let a = (-2.5)..8
let b = 10|min|...15|min|
let c = 5|lb|..20|kg|
let d = ...20
let e = 0|s|..

The parentheses around -2.5 are there for a reason. The range operator binds tighter than the minus sign, so -2.5..8 would read as -(2.5..8), the range from −8 to −2.5. The same goes for boundaries that are read from a collection: write (load.min)..(load.max).

Operators

Composite ranges can be built out of simple ones with the operators + and -. For example

1...4 - 2..3

is a range made of two pieces: from 1 up to 2, and from 3 up to 4.

Arithmetic between ranges:

Symbol Name Example Result
+ union 1..2 + 3...5 1..2 and 3...5
- difference `3 lb

Arithmetic between a range and a number or a measurement moves the whole range:

Symbol Name Example Result
+ displace 1..2 + 3 4..5
- displace `10 min

Comparison between ranges:

Symbol Name Example Result
== equals 1..2 == 1...2 false
< strictly less than 0..1 < 1..2 true
> strictly greater than 5..8 > 3..5 true

Containment checks whether a value falls inside a range. The <> operator works in both directions:

Symbol Name Example Result
<> contained in 4 <> 3..5 true
<> contains `1 kg

The same <> also checks whether a value is one of the items of an array: "Wide" <> ["Wide", "Close"] is true.

String

A string is any sequence of characters between double quotation marks "".

Example

"This is a string"
"日本人 are awesome"
"Say \"go\" and lift"

A few characters need a backslash in front of them: \" for a double quote, \\ for a backslash and \n for a new line. The grammar lists them all.

Operators

Symbol Name Example Result
+ concatenation "Hello" + " world" "Hello world"
+ concatenation "Set " + 3 "Set 3"

A string on the left can be joined with a number on its right, which is handy for titles. The other way around, 3 + "rd set", is an error; start with an empty string instead: "" + 3 + "rd set".

Boolean

Boolean values are written true and false. They are what comparisons produce, and they combine with the logical operators:

Symbol Name Example Result
&& and true && false false
` ` or
! not !true false

Nil

nil is a special value that denotes no value. It is what you get when you read something that is not there, for example a key that a map does not have, or an optional input the athlete left blank. In a condition, nil counts as false.

Choosing between values

The conditional operator picks one of two values based on a condition:

let reps = 4
let rest_time = reps < 5 ? 3|min| : 2|min|

If the condition holds, the result is the value after the ?; otherwise it is the value after the :.

Expressions

One very important fact we have to mention is that wherever Coach expects a value, you can give it an expression. An expression is one, or a combination (via the operators above), of the following:

  • a primitive value: a number, a measurement, a string and so on,
  • a name that stands for a value, such as an exec or group parameter, a variable or a stored feedback,
  • a call to an exec, a group or a built-in function.

Example

These are what expressions might look like:

let athlete_weight = 55|kg|
let athlete_age = 30
let i = 2

// Simple expressions
220|lb|
false
63 - 12
35|m| / 12|s|

// More involved expressions
12|min| <= 4 * 60|s|
athlete_weight <> 50|kg|...60|kg|
round(athlete_weight * 0.8, 2.5|kg|) == 45|kg|
athlete_age > 25 && (10 + i) % 2 == 0

When an expression mixes several operators, Coach applies them in a fixed order: * before +, comparisons before &&, and so on. The grammar lists the complete order. When in doubt, use parentheses.