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.