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 file module
  • Network: functions from the http and server modules

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
    }
}