Library
Capability interfaces
IEnv, IConsole, IClock, IFileSystem and INet: injectable stand-ins for the ambient environment, console, clock, files and network.
since 0.1.0-alpha.1linuxwindowswasm
Description
The standard library offers five small interfaces, one for each way a program normally reaches the
outside world. Each is an alternative to an ambient global: instead of reading env::args() or
calling console.writeln directly, a function can ask for the capability as a parameter and let
dependency injection (bind and inject) fill it in.
| Interface | What it offers | The ambient equivalent |
|---|---|---|
IEnv |
args(), variable(name) (None when unset) |
env::args(), env::get(name) |
IConsole |
write(s), writeln(s), writeln() |
console |
IClock |
now(), milliseconds since the epoch |
the system clock |
IFileSystem |
open(path, mode) returning a File, exists(path) |
File, std::fileExists |
INet |
connect(host, port) returning TcpStream? (None on failure), listen(port) returning a TcpListener |
TcpStream, TcpListener |
Each has one real implementation, a small stateless class that forwards to the ambient surface:
SystemEnv, SystemConsole, SystemClock, SystemFileSystem and SystemNet. Because they are
the only implementation underneath, injected code and ambient code behave identically.
All five are in the std namespace, so the names are visible everywhere. Visibility is not
provision: nothing is bound just because a name is visible. The real implementation of a
capability is activated only by an explicit use std::IClock; (and so on), which installs the
standard binding for that interface into the scope where the use is written. An explicit bind
of your own, written closer to the call, always wins, which is how you substitute a fake.
Injecting a fake clock
use std::IConsole;
use std::IClock;
class FakeClock : IClock {
int ms;
new FakeClock(int start) { ms = start; }
int now() {
ms += 250;
return ms;
}
}
int elapsed(IClock clock, IConsole out) {
int start = clock.now();
out.writeln("started at ${start}");
int end = clock.now();
out.writeln("finished at ${end}");
return end - start;
}
void run() {
bind IClock => FakeClock(1000);
console.writeln("elapsed ${elapsed()} ms");
}
run();
started at 1250
finished at 1500
elapsed 250 ms
elapsed never mentions a concrete clock or console. The use lines provide the real console;
the bind inside run replaces the clock with one that advances by 250 milliseconds on every
call, so the output is the same on every run.
Rules
- A capability is a claim, not an enforced sandbox. The ambient globals (
console,env,File, and the rest) stay reachable from anywhere whatever a function signature says. The guarantee is that the disciplined path, taking one injected parameter, is cheaper than the ambient one; the compiler does not forbid the other. - A
bindmust enclose the call that needs it. Binding inside a function reaches only the calls made from inside that function. IEnv.variablereadsenv::get:Nonemeans unset, which is different from set to an empty string.INet.connectreturnsNonewhen the connection fails, where a raw connection would report failure with a silent no-op write.IFileSystemandINetcontrol how aFile,TcpStreamorTcpListeneris acquired; they hand back the real objects, and what those objects can do is unchanged.- The same implementation sits under both the injected and the ambient path.
Examples
See the program above for a fake clock. A fake IEnv is shown in std.env.
See also
- IEnv — What a program may learn from the process environment: its arguments and its variables.
- IConsole — What a program may say to the terminal.
- IClock — What a program may know about the time.
- IFileSystem — What a program may do with the file system: open files and check whether a path exists.
- INet — What a program may do with the network: open connections and listen for them.
- SystemEnv — The real process environment behind the
IEnvinterface. - SystemConsole — The real console behind the
IConsoleinterface: it prints to standard output. - SystemClock — The real clock behind the
IClockinterface. - SystemFileSystem — The real file system behind the
IFileSysteminterface. - SystemNet — The real network behind the
INetinterface. - env — The running process: its command-line arguments, its environment variables, and how it exits.