The language
Imports
Splitting a program into several files and using what the standard library already defines.
A small program fits comfortably in main.cl. A bigger one, say a twelve-week
cycle with a warm-up, three different days and a deload, reads much better
when it is split into several files. And almost every program wants to use
what the standard library already defines rather than write its own
bench press. Both are done with import.
Importing a file
An import names the file to bring in, as a string:
import "coach/common/rest.cl"
rest(2|day|)
Everything the imported file declares, i.e. its actions, inputs, outputs,
execs, groups and top-level variables, becomes available as if it had been
written in the importing file. Above, rest comes from
coach/common/rest.cl.
A few rules apply:
- Imports go at the very top of a file, before anything else.
- The path includes the
.clextension. - Paths start from the
srcfolder of your program, whichever file the import is written in. A file atsrc/weeks/week1.clis imported as"weeks/week1.cl", both frommain.cland fromsrc/weeks/week2.cl. - Paths that start with
coach/point into the standard library.
Example
Let us move the days of our program into a file of their own,
src/days.cl:
import "coach/strength/squat.cl"
import "coach/strength/push.cl"
let logged = [reps: true, weight: true]
group day_a() {
@title = "Day A"
squat([weight: 80|kg|, reps: 5], logged, [location: true])
bench_press([weight: 60|kg|, reps: 5], logged, [location: true])
}
main.cl then only has to import it and say when each day happens:
import "days.cl"
import "coach/common/rest.cl"
repeat 4 {
day_a()
rest(2|day|)
}
Notice that main.cl imports coach/common/rest.cl itself. Imports are not
passed along: a file sees what it declares and what it imports, but not
what the files it imports have imported in turn. main.cl above can call
day_a, but not squat, unless it imports coach/strength/squat.cl too.
It is perfectly fine for two files to import each other, or for several files to import the same one.
Naming an import
Sometimes two files declare the same name. The standard library’s
coach/athlete.cl and coach/strength/elements.cl, for example, both declare
an input called weight: one is the athlete’s body weight, the other the
weight on the bar. To keep them apart, give an import a name with as:
import "coach/athlete.cl" as athlete
exec weigh_in() {
@title = "Weigh-in"
measure athlete.weight
}
weigh_in()
Everything from an import named this way is reached through its name, with a
dot: athlete.weight, athlete.age. Nothing from it is available without the
prefix.
Naming imports also makes it obvious, when you read a program months later, where each name comes from.
The standard library
Every program depends on the standard library, called coach. It is there
from the moment you create a program, so there is nothing to install: an
import is all it takes. The library is released in versions, and a new program
uses the latest release. All of the library’s files are documented under
Standard library, along with the exact path to import each one from.