Learn
Lesson 19

Modules and imports

Split a program across files and folders, choose what each file exposes, and use packages from the standard library, Git and Go.

One file goes a long way, but real programs grow. import brings in code from another file, a folder, the standard library, a Git repository or Go.

Importing a file#

Put shared code in its own file and import it by its path, relative to the file doing the importing. Everything the file declares becomes available:

import "./shapes.osl"

log area(circle(2))
log area(square(3))
Click the code to edit it

The two tabs above are one program: main.osl imports shapes.osl. Click a tab to see each file.

Importing a folder#

import "shapes", without ./ or .osl, imports every .osl file directly inside the folder shapes. It's the usual way to group a feature's files together:

main.osl
api/
  routes.osl
  handlers.osl
db/
  users.osl
  queries.osl
osl
import "api"
import "db"

Files in a folder are loaded in alphabetical order. Subfolders aren't included; import each one you need.

Choosing what a file exposes#

Without an export line, a file exposes everything it declares. Add one to make a file's public API explicit; the rest stays private to the file and its folder:

import "./counter.osl"

log next()
log next()
Click the code to edit it

main.osl can call next, but not format or count.

Importing parts, or a namespace#

Pick names from a file, or put everything under a prefix to avoid clashes:

import {celsius} from "./convert.osl"
import * as convert from "./convert.osl"

log celsius(212)
log convert.fahrenheit(100)
Click the code to edit it

The standard library#

Packages that ship with the compiler start with std:. They cover servers, files, JSON, databases, images, threads and much more; the package pages have a tutorial for each:

main.osl
import "std:json"
import "std:math"

log json.stringify({ok: true, values: [1, 2]})
log math.pi.toStr().left(4)
Click the code to edit it

set, map, result and a few other core types are built in and need no import to use as types.

Git packages#

Opal, the package manager that installs with OSL, adds packages from Git repositories:

Terminal
opal init
opal add someone/some-package

Then import it by its repository name: import "someone/some-package". Opal pins the exact version in opal.lock, so everyone building the project gets the same code. The Opal reference has the details.

Go packages#

Any Go package is an import away, with the go: prefix. The Go lesson covers this properly:

main.osl
import "go:strings"

log strings.Repeat("ab", 3)
log strings.Title("hello world")
Click the code to edit it

Organising a project#

A layout that scales well: one entry file that wires things together, and a folder per area of the program.

src/
  main.osl        imports the folders, starts the program
  api/            HTTP routes and handlers
  db/             storage and queries
  helpers/        small shared functions

Keep main.osl short. If it's doing real work, that work probably belongs in a folder.

Quick check

What does import "utils" import?

Your turn

Use the standard library

Import std:json and print the object as JSON text, instead of with log alone.

main.osl
Ctrl Enter runs
Expected output
{"size":14,"theme":"dark"}
0 of 24 lessons done