Expressions
Y is an expression-oriented language, meaning that most constructs evaluate to a value. Understanding expressions is fundamental to writing effective Y code.
What is an Expression?
An expression is a piece of code that evaluates to a value. In Y, almost everything is an expression, including:
- Literals (numbers, strings, booleans)
 - Variable references
 - Function calls
 - Arithmetic operations
 - Conditionals (if-else)
 - Blocks
 - Lambdas
 
Basic Expressions
Literal Expressions
42          // Integer literal
3.14        // Floating point literal
"hello"     // String literal
'a'         // Character literal
true        // Boolean literal
false       // Boolean literal
Variable Expressions
let x = 42;
let y = x;  // x is an expression that evaluates to 42
Arithmetic Expressions
let a = 10;
let b = 5;
let sum = a + b;        // Addition expression
let product = a * 2;    // Multiplication expression
let complex = (a + b) * 2 - 1;  // Complex arithmetic expression
Function Call Expressions
Function calls are expressions that evaluate to the return value:
fn add(x: i64, y: i64): i64 {
    x + y  // This is also an expression (the last one in the function)
}
let result = add(10, 20);  // Function call expression
let nested = add(add(1, 2), add(3, 4));  // Nested function calls
Conditional Expressions
If-else constructs are expressions in Y:
let max = if (a > b) {
    a
} else {
    b
};
// Can be used directly in other expressions
let result = if (x > 0) { x } else { -x } + 10;
Block Expressions
Blocks evaluate to the value of their last expression:
let result = {
    let x = 10;
    let y = 20;
    x + y  // This value becomes the result of the block
};  // result is 30
Lambda Expressions
Lambdas are expressions that create anonymous functions:
let add_one = \(x) => x + 1;
let multiply = \(x, y) => x * y;
// Using lambda expressions directly
let numbers = &[1, 2, 3];
let transformed = map(numbers, \(x) => x * 2);
Array Expressions
Array literals are expressions:
let numbers = &[1, 2, 3, 4, 5];
let empty = &[];
let mixed = &[add(1, 2), multiply(3, 4), 42];
Struct Initialization Expressions
Creating structs is also an expression:
struct Point {
    x: i64;
    y: i64;
}
let origin = Point { x: 0, y: 0 };
let point = Point {
    x: calculate_x(),
    y: calculate_y()
};
Property Access Expressions
Accessing struct fields and calling methods:
let person = Person { name: "Alice", age: 25 };
let name = person.name;        // Property access expression
let id = person.get_id();      // Method call expression
Practical Examples
Expression-Heavy Function
fn calculate_distance(x1: f64, y1: f64, x2: f64, y2: f64): f64 {
    // Everything here is composed of expressions
    let dx = x2 - x1;
    let dy = y2 - y1;
    sqrt(dx * dx + dy * dy)  // Final expression becomes return value
}
Chaining Expressions
fn main(): i64 {
    let my_struct = TestStruct {
        x: 42,
        bar: add
    };
    // Chaining property access and function call expressions
    let result = my_struct.bar(10, 20);
    // Complex expression with multiple parts
    let final_result = if (result > 0) {
        result + my_struct.x
    } else {
        my_struct.x * 2
    };
    return final_result;
}
Expression Composition
fn process_data(): i64 {
    let data = &[1, 2, 3, 4, 5];
    // Composed expression using array access, function calls, and arithmetic
    let result = process_value(data[0]) +
                 process_value(data[1]) * 2 +
                 if (data[2] > 3) { data[2] } else { 0 };
    return result;
}
Statement vs Expression
While most things in Y are expressions, some constructs are statements:
// Statements (don't evaluate to values):
let x = 42;              // Variable declaration
x = 100;                 // Assignment
return x;                // Return statement
// Expressions (evaluate to values):
x + y                    // Arithmetic
if (x > 0) { x } else { -x }  // Conditional
{                        // Block
    let temp = x + 1;
    temp * 2
}
Best Practices
- Leverage expression-oriented style: Use the fact that if-else and blocks are expressions
 - Keep expressions readable: Break complex expressions into intermediate variables when needed
 - Use the last expression in functions: Instead of explicit 
return, let the last expression be the return value - Compose expressions thoughtfully: Balance conciseness with clarity
 
// Good: Clear and expressive
fn clamp(value: i64, min: i64, max: i64): i64 {
    if (value < min) {
        min
    } else if (value > max) {
        max
    } else {
        value
    }
}
// Also good: Breaking down complex logic
fn complex_calculation(input: i64): i64 {
    let base = input * 2;
    let adjusted = base + 10;
    if (adjusted > 100) { 100 } else { adjusted }
}