leviathan-lang.com / docs / learn
Functions, generics and injection
Functions and methods, named and default arguments, generic inference, and bind/inject.
Functions and arguments
A function has no this (it lives in a namespace or a class's static side); a method has
one. Both overload by argument type, and both support named arguments and default parameters. A
body is exactly one statement: use a block or an arrow.
Defaults and named arguments
int add(int a, int b) => a + b;
void greet(string name, string greeting = "Hello") {
console.writeln("${greeting}, ${name}!");
}
console.writeln(add(2, 3));
greet("Ada"); // "Hello, Ada!"
greet("Alan", greeting: "Hi"); // named argument reorders freely
5
Hello, Ada!
Hi, Alan!
Generics
Generics infer their type arguments from the call, and fall back to the target type:
Inferred type arguments
T firstOr<T>(Array<T> xs, T dflt) => xs.isEmpty() ? dflt : xs.first();
int x = firstOr([1, 2, 3], 0); // T = int, inferred from the argument
string s = firstOr([], "none"); // T = string, from the default
console.writeln(x);
console.writeln(s);
1
none
Injection
For wiring dependencies, bind supplies a value and inject requests one. A parameter you leave
out of a call is filled from the nearest enclosing bind of its type. Binding is lexical and
nearest-wins, and it must enclose the call site, not the callee: a bind inside a function body
only reaches calls made from inside that body. That is what makes swapping a real dependency for a
fake in tests a one-line change.
bind encloses the call, so swapping is one line
interface ILogger { void log(string s); }
class ConsoleLogger : ILogger { public void log(string s) => console.writeln(s); }
class QuietLogger : ILogger { public void log(string s) => console.writeln("(quiet) ${s}"); }
void audit(ILogger logger) {
logger.log("audit ran");
}
void run() {
bind ILogger => ConsoleLogger(); // in scope for the call below
audit(); // its ILogger parameter is filled by injection
}
void runQuietly() {
bind ILogger => QuietLogger(); // the one line that changes
audit();
}
run();
runQuietly();
audit ran
(quiet) audit ran