Expressions
Primary expressions
Literals, names, this, parentheses, array and range literals, lambdas and string interpolation, the building blocks of every other expression.
since 0.1.0-alpha.1linuxwindowswasm
Description
A primary expression is the smallest unit an operator or a call can act on:
| form | meaning |
|---|---|
42 3.14 "s" true false |
a literal |
name |
a local variable, a parameter, a member, a function or a type |
this |
the enclosing instance, or the receiver value inside a method of a primitive type |
(expr) |
grouping |
[e1, e2, ...] |
an array literal; a range inside the brackets is spread into its elements |
a .. b |
a range value, both endpoints included |
(p1, p2) => expr |
a lambda; its parameters are written without types and it captures the variables it uses |
await expr |
a suspension point that parks the current task until expr completes |
inject Type |
an explicit injection selector for Type |
Literals, grouping, arrays, ranges and lambdas
class Sink {
int total = 0;
Sink (<<)(int n) {
total = total + n;
return this;
}
}
void apply((int) => void f) {
f(5);
}
void main() {
int x = 5;
console.writeln((x + 1) * 2);
Array<int> listed = [10, 20, 30];
Array<int> spread = [1..4];
console.writeln(listed);
console.writeln(spread);
var inc = (n) => n + 1;
console.writeln(inc(4));
var sum = (p, q) => {
int t = p + q;
return t * 2;
};
console.writeln(sum(1, 2));
Sink sink = Sink();
apply((n) => sink << n);
console.writeln(sink.total);
}
main();
12
[10, 20, 30]
[1, 2, 3, 4]
5
6
5
Rules
- A lambda body is either an expression (
(x) => x + 1) or a statement block ((x) => { ...; return y; }). - An expression body in a position where the lambda must return
voidis treated as a statement: its value is discarded, exactly like an expression statement. That is whyapply((n) => sink << n)is legal even though<<returns its receiver. A block body that returns a value wherevoidis expected is still an error, and a lambda whose expected return type is notvoidhas its body checked against that type. - A lambda captures a primitive local variable (
int,float,bool,string) by snapshot: a later change to the variable is not seen by the lambda, and a change the lambda makes to its own copy is not seen outside. To share mutable state, capture an object and change its fields. thisis available only inside a class body; using it elsewhere is a compile error.- A range
a .. bincludes both endpoints. Inside array brackets the range is spread:[1..4]is[1, 2, 3, 4]. - Several keywords (
get,set,is,inand others) may be used as member names after.or::and as method names after a return type. They are keywords only at the start of a statement or declaration.
String interpolation
"...${expr}..." inserts the text of expr into the string. It works in both quote styles and is shorthand for concatenating the string pieces with the toString() of each hole, so a hole may contain any expression whose type has a toString().
\${writes a literal${.- A lone
$that is not followed by{is an ordinary character. - An empty hole (
${}) and an unterminated hole are compile errors. - A string literal inside a hole must use the opposite quote style from the string that contains it:
"${'has a } in it'}"is valid, while a nested literal with the same quote character ends the outer string at that point.
Interpolation
int x = 5;
console.writeln("x=${x}, next=${x + 1}");
console.writeln("literal \${x} and a $ sign");
console.writeln("${'has a } in it'}");
console.writeln('${"double quotes inside"}');
x=5, next=6
literal ${x} and a $ sign
has a } in it
double quotes inside
Examples
A lambda captures primitives by snapshot and objects by reference
class Box {
int n = 0;
}
void main() {
int seen = 0;
var bump = () => { seen = seen + 1; };
bump();
bump();
console.writeln(seen);
Box box = Box();
var inc = () => { box.n = box.n + 1; };
inc();
inc();
console.writeln(box.n);
int base = 10;
var add = (x) => x + base;
base = 100;
console.writeln(add(1));
}
main();
0
2
11
Keywords as member names
class Gate {
int in = 3;
bool is() => true;
int get() => 7;
}
Gate g = Gate();
console.writeln(g.in);
console.writeln(g.is());
console.writeln(g.get());
3
true
7
Notes
- A variable that holds a function value, such as
var inc = (n) => n + 1;, is called withinc(4)inside a function body. Declare such variables inside a function. varandletdeclarations, which infer the type from the initializer, are accepted inside function bodies and inside the body of a control statement. At the outermost level of a script, write the declared type instead.awaitandinjectare covered with the features they belong to (tasks and dependency injection).