Functional
Apply Blocks (Context Blocks)
Overview
Apply blocks allow executing operations in the context of an expression's result. This is analogous to .apply{} in Kotlin, but with a more concise syntax — just curly braces {} after any expression.
Syntax
<expression> {
# inside the block, a special variable `it` is available
# which references the result of the expression on the left
}Basic Examples
Object Initialization
class Person(str name, int age) {
func setName(str n) void { name = n; }
func setAge(int a) void { age = a; }
}
# Without apply block:
Person p = new Person("", 0)
p.setName("John")
p.setAge(25)
# With apply block:
Person p = new Person("", 0) {
it.setName("John")
it.setAge(25)
}Call Chaining
str result = "hello" {
it = it + " world"
it = it + "!"
}
# result = "hello world!"Working with Arrays
array[int] arr = new array[int](5) {
it[0] = 1
it[1] = 2
it[2] = 3
it[3] = 4
it[4] = 5
}Nested Apply Blocks
class Point(int x, int y) {
func setX(int val) void { x = val; }
func setY(int val) void { y = val; }
}
class Line(Point start, Point end) {}
Line line = new Line(new Point(0, 0), new Point(0, 0)) {
it.start {
it.setX(10)
it.setY(20)
}
it.end {
it.setX(100)
it.setY(200)
}
}Semantics
- Context variable
it: Inside an apply block, a special variableitis available, containing a reference to the result of the expression to the left of{}. - Return value: An apply block always returns the value of
it(even if the last expression in the block returns something else). - Type: The type of an apply block matches the type of the expression on the left.
- Scope: The variable
itis only available inside the apply block and shadows any outer variables with the same name.
Advanced Examples
Modification and Return
# Creation and initialization in a single expression
func createConfiguredPerson() Person {
return new Person("", 0) {
it.setName("Default")
it.setAge(18)
}
}Working with Dictionaries
dict[str:int] scores = new dict[str:int]{} {
it["Alice"] = 100
it["Bob"] = 95
it["Charlie"] = 87
}Conditional Initialization
Person p = new Person("", 0) {
if (needsDefault) {
it.setName("Anonymous")
} else {
it.setName(userName)
}
it.setAge(calculateAge())
}Edge Cases
Apply Block with Primitives
int x = 5 {
it = it * 2 # it = 10
}
# x = 10Empty Apply Block
Person p = new Person("John", 25) {}
# Equivalent to: Person p = new Person("John", 25);Chained Apply Blocks
Person p = new Person("", 0) {
it.setName("John")
} {
it.setAge(25)
}Apply Block in Expression
int total = (new Counter() { it.add(5); }).value + 10