The prelude
The prelude is the package whose public names are in scope in every file without an import, and it holds only the pure part of the standard library.
Diese Seite gibt es noch nicht auf Deutsch, deshalb steht sie hier auf Englisch. Zur englischen Seite
A new file already has Option, List, print and every other name of the glossary in
scope. use is for everything else: the prelude is what a project decided nobody should have to import.
Example#
const numbers = [1, 2, 3]
print numbers.map({ _ * 2 }).toList()Nothing here is imported: List, the closure syntax, map and print are all part of std/prelude.
Syntax#
use <Name> from "std/prelude" // Legal, but redundant for a name the prelude already exportsRules#
std/preludedeclares nothing of its own. Itssrc/lib.trbis nothing butpublic use ... from "std/..."lines, so every name it re-exports can also be imported straight from the package that declares it.That includes members other packages attach to a type:
public use Int64.seconds from "std/time"is why2.seconds()works everywhere, althoughstd/timedoes not ownInt64. See extend for why such a member is named at all, and use for the form.print 2.seconds()A project's prelude is
std/preludeunlessproject.trbnames another one. The field ispreludeonProject, so a teaching subset or the vocabulary of an embedded DSL can replace it for a whole project.The prelude holds the pure part of the standard library, and none of its capabilities. Values, text, numbers, collections, pipelines, encoding, quotations, tasks and printing are in scope everywhere;
std/fs,std/os,std/process,std/io,std/http,std/sandboxandClockare not.Kompiliert nichtfn checkExists(path: String): Bool { File.exists path } // error: Cannot find `File` hereAn import of a capability is a statement a reviewer can read at the top of the file.
use File from "std/fs"says "this file touches files" before a single line of its body does, which is exactly what a name that was already in scope could never say.A sandbox gives its script the prelude of the host plus the receiver, and nothing else. A receiver script is defined that way, which is why the split between the prelude and every capability package is what makes the sandbox possible at all.
The prelude ranks below everything a file wrote or imported. A name the file declares or imports - under an
asname too, and a case it imports - shadows the prelude's name of that spelling. For a member, what the file wrote or named itself answers before what it reaches only through its prelude, whatever the specificity of either: a file's ownextend<Item> Iterate<Item>member beats aListmember the prelude re-exports, and ause String.shout from "acme/text"beats aString.shoutof the prelude. Two members of the same rank are still the ambiguity at the use (see use). So the prelude can grow in a minor release: a name, member or trait it gains never breaks a program and never changes what it means.
What this is not#
The prelude is not "everything the standard library has". A name that is not re-exported by std/prelude needs
its own use, however small it looks.
use Clock from "std/time"
const start = Clock.now()
const elapsed: Duration = Clock.now() - start
print elapsedconst start = Clock.now()
// error: Cannot find `Clock` hereInstant, Duration, Timestamp and ByteSize need no import - they are values, and every field of a program can
hold one.
Clock reads the clocks of the machine, which is a capability, and only an explicit use brings it into scope.
Path is the same split: a path is a value that names a file and needs no import, and File, which opens what it
names, comes from std/fs.
const config = Path.from "project.trb"
print config.extension()Related#
- std/prelude - every name this package re-exports today.
- use - every form an import can take.
- Packages - what a package is, and how the prelude is one.
- Visibility -
public, which is what makes a name re-exportable at all.