Conditionals
Conditionals in Stone are expressions that produce values. When used in an assignment, all branches must produce a value and an else branch is required. When used for side effects only, the else branch is optional.
Value-Returning Conditionals
When a conditional appears on the right side of an assignment, it must produce a value. The last expression in each branch is the value it produces:
result = if (x > 0) { "positive" } else { "negative" }
With multiple branches:
category = if (score >= 90) { "A" }
elif (score >= 80) { "B" }
elif (score >= 70) { "C" }
else { "F" }
Multi-Statement Branches
Branches can contain multiple expressions. The last expression provides the value:
message = if (score >= 90) {
print("Excellent!")
"You passed with distinction: A"
} elif (score >= 60) {
"You passed: B"
} else {
"Please try again: F"
}
Use return(expr) for early exit from a function:
fn process(items) {
if (items == []) { return("empty") }
// ... process items
"done"
}
Side Effects in Stone
Stone is a functional language — most code is pure computation with no side effects. The only operations that produce side effects are:
- Output:
print,display,show - File I/O: functions from the
filemodule - Network: functions from the
httpandservermodules
Side-effect conditionals appear without an assignment target. No return value is needed and the else branch is optional:
if (x > threshold) {
print("Warning: value exceeded threshold")
}
if (level == "error") {
print("ERROR: something went wrong")
} elif (level == "warn") {
print("Warning: check this out")
}
// no else needed
Conditionals in Loops
Side-effect conditionals are commonly used inside loops for conditional state updates:
positive_sum = evolve (positive_sum = 0) for (x in xs) {
if (x > 0) {
positive_sum' = positive_sum + x
}
}
Or for early exit:
found = evolve (found = false) for (x in xs) {
if (x == target) {
found' = true
break
}
}
else if Syntax
else if is accepted as a synonym for elif:
category = if (score >= 90) { "A" }
else if (score >= 80) { "B" }
else if (score >= 70) { "C" }
else { "F" }
Both forms are interchangeable — use whichever you prefer. elif is shorter; else if is more familiar from other languages.
Match Expression
The match expression dispatches on a value using literal patterns. Like if, it is an expression and produces a value:
label = match code {
1 { "one" }
2 { "two" }
3 { "three" }
else { "other" }
}
Each arm is a literal value followed by a block. The else arm is the default — it handles anything not covered by earlier arms.
Arms can contain multi-statement logic:
result = match shape {
"circle" {
area = PI * r * r
{ kind = "circle", area }
}
"square" {
area = side * side
{ kind = "square", area }
}
else { error("unknown shape: " + shape) }
}
Side-effect match (no assignment, no else arm required):
match event {
"click" { print("clicked") }
"hover" { print("hovered") }
}
For conditional logic with ranges or comparisons, use if/elif/else instead of match.
Nested Conditionals
Conditionals can be nested within branches:
result = if (x > 0) {
if (x > 100) { "large positive" } else { "small positive" }
} else {
"not positive"
}
Examples
Absolute value:
abs_x = if (x >= 0) { x } else { -x }
Clamping a value to a range:
clamped = if (x < min) { min }
elif (x > max) { max }
else { x }
Logging based on verbosity:
if (verbose) {
print("Processing item: " + item)
}
Assigning a default:
name = if (input != "") { input } else { "anonymous" }
Conditional inside a loop to find min and max:
min, max := evolve { min = xs[0], max = xs[0] } for (x in xs) {
if (x < min) {
min' = x
}
if (x > max) {
max' = x
}
}
Classifying values while counting:
pos, neg, zero := evolve { pos = 0, neg = 0, zero = 0 } for (x in xs) {
if (x > 0) {
pos' = pos + 1
} elif (x < 0) {
neg' = neg + 1
} else {
zero' = zero + 1
}
}