Expressions
Strictness
What the compiler rejects instead of guessing, and which failures are left to run time as catchable exceptions.
since 0.1.0-alpha.1linuxwindowswasm
Description
Leviathan prefers a compile error to a guess. A program that names something that does not exist, leaves a generic type argument without a source, or mixes unrelated types in a declaration is rejected before it runs. What the compiler cannot decide ahead of time fails at run time with a RuntimeException that a program can catch.
Failures that surface at run time are catchable
Array<int> xs = [1, 2, 3];
try {
console.writeln(xs[5]);
} catch (RuntimeException e) {
console.writeln("array: ${e.message}");
}
try {
console.writeln(10 / 0);
} catch (RuntimeException e) {
console.writeln("math: ${e.message}");
}
array: index 5 out of bounds (length 3)
math: division by zero
Map<string, int> m = Map();
try {
console.writeln(m.at("missing"));
} catch (RuntimeException e) {
console.writeln("map: ${e.message}");
}
class Plain {
int v = 1;
}
Plain p = Plain();
try {
console.writeln(p + p);
} catch (RuntimeException e) {
console.writeln("operator: ${e.message}");
}
// map: key not found: missing
// operator: no operator '+' on 'Plain'
Rules
- An unknown name or function is a compile error.
- A generic construction whose type argument has no source is a compile error. Provide a target type, an argument that carries the type, or an explicit construction tuple such as
Box::<int>(). A type argument is inferred when it can be recovered, written explicitly when you want to, and required when it cannot be recovered. - Explicit type arguments on a call must match the number of type parameters exactly and are authoritative. A value that conflicts with a type the explicit arguments pin is a compile error at that argument.
- A prefix operator on the wrong primitive is a compile error:
!outsidebool,-outside the numeric types,~outside the integer types. Seelang.prefix-operators. - A value of one kind is not accepted where an unrelated kind is declared:
string s = 5;,int y = "5";,bool b = 1;andint n = 1 + "2";are compile errors. - Runtime failures throw a
RuntimeExceptionthat can be caught: an index out of bounds,aton a map with a missing key, an integer division by zero, a call whose target cannot be resolved, and a binary operator that the left operand's class does not define.
Examples
console.writeln(undefinedName);
// error: unknown name 'undefinedName'
undefinedFunction(3);
// error: unknown function 'undefinedFunction'
class Box<T> { T v; }
Box b = Box();
// error: cannot infer type argument 'T' for 'Box'; provide a target type or a type-bearing argument
string s = 5;
// error: cannot initialize 's' with 'int'
Providing the type argument explicitly
class Box<T> {
T value;
}
Box<int> a = Box::<int>(5);
console.writeln(a.value);
5
Notes
Numeric values adopt the declared numeric type at a declaration, so float z = 3; holds 3.0, and conversions between numeric types follow the numeric-conversion rules. Conditions in if and while are meant to be bool; write an explicit comparison such as n != 0 rather than relying on a number as a condition.
See also
- RuntimeException — The error the standard library throws when an operation fails at run time.
- Prefix operators — The operand types accepted by the unary operators !, - and ~, and the results they produce.