Advanced Language Features

Now that we have a solid foundation, let's add powerful features that make Lux practical: enhanced list operations, string manipulation, advanced loop constructs, and more.

Lists in Depth

We already have basic lists. Let's explore their full capabilities.

List Creation

let empty = [];
let numbers = [1, 2, 3, 4, 5];
let mixed = [1, "hello", true, nil, [1, 2]];  // Heterogeneous
let nested = [[1, 2], [3, 4], [5, 6]];

List Indexing

let items = ["a", "b", "c", "d"];
print items[0];   // "a"
print items[3];   // "d"
print items[10];  // Error: List index 10 out of bounds

List Modification

let numbers = [1, 2, 3];

// Add elements
push(numbers, 4);
push(numbers, 5);
print numbers;  // [1, 2, 3, 4, 5]

// Remove elements
let last = pop(numbers);
print last;     // 5
print numbers;  // [1, 2, 3, 4]

List Iteration

let fruits = ["apple", "banana", "cherry"];

for fruit in fruits {
    print "I like " + fruit;
}
// Output:
// I like apple
// I like banana
// I like cherry

List Operations with Higher-Order Functions

// Map
fn map(list, f) {
    let result = [];
    for item in list {
        push(result, f(item));
    }
    return result;
}

let numbers = [1, 2, 3, 4, 5];
let squares = map(numbers, fn(x) { return x * x; });
print squares;  // [1, 4, 9, 16, 25]

// Filter
fn filter(list, predicate) {
    let result = [];
    for item in list {
        if predicate(item) {
            push(result, item);
        }
    }
    return result;
}

let evens = filter(numbers, fn(x) { return x % 2 == 0; });
print evens;  // [2, 4]

// Find
fn find(list, predicate) {
    for item in list {
        if predicate(item) {
            return item;
        }
    }
    return nil;
}

let first_big = find(numbers, fn(x) { return x > 3; });
print first_big;  // 4

// Any/Some
fn any(list, predicate) {
    for item in list {
        if predicate(item) {
            return true;
        }
    }
    return false;
}

print any(numbers, fn(x) { return x > 10; });  // false
print any(numbers, fn(x) { return x > 3; });   // true

// All
fn all(list, predicate) {
    for item in list {
        if not predicate(item) {
            return false;
        }
    }
    return true;
}

print all(numbers, fn(x) { return x > 0; });   // true
print all(numbers, fn(x) { return x > 3; });   // false

List Building Patterns

// Range function (utility)
fn range(start, end) {
    let result = [];
    let i = start;
    while i < end {
        push(result, i);
        i = i + 1;
    }
    return result;
}

let nums = range(0, 10);
print nums;  // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

// List comprehension (manual)
fn comprehension(limit, transform, condition) {
    let result = [];
    let i = 0;
    while i < limit {
        if condition(i) {
            push(result, transform(i));
        }
        i = i + 1;
    }
    return result;
}

let even_squares = comprehension(10,
    fn(x) { return x * x; },
    fn(x) { return x % 2 == 0; }
);
print even_squares;  // [0, 4, 16, 36, 64]

String Operations

Strings in Lux are immutable sequences of characters.

String Concatenation

let first = "Hello";
let last = "World";
let full = first + ", " + last + "!";
print full;  // "Hello, World!"

// Concatenate with numbers
let age = 30;
print "I am " + str(age) + " years old";  // "I am 30 years old"

String Indexing

let word = "Hello";
print word[0];  // "H"
print word[4];  // "o"
print word[5];  // Error: String index 5 out of bounds

String Length

let message = "Hello, World!";
print len(message);  // 13

String Iteration

let word = "Lux";
let i = 0;
while i < len(word) {
    print word[i];
    i = i + 1;
}
// Output:
// L
// u
// x

String Building

fn join(list, separator) {
    if len(list) == 0 {
        return "";
    }
    
    let result = str(list[0]);
    let i = 1;
    while i < len(list) {
        result = result + separator + str(list[i]);
        i = i + 1;
    }
    return result;
}

let words = ["one", "two", "three"];
print join(words, ", ");  // "one, two, three"

String Utilities

// Repeat string
fn repeat_string(s, n) {
    let result = "";
    let i = 0;
    while i < n {
        result = result + s;
        i = i + 1;
    }
    return result;
}

print repeat_string("*", 5);  // "*****"

// Reverse string
fn reverse_string(s) {
    let result = "";
    let i = len(s) - 1;
    while i >= 0 {
        result = result + s[i];
        i = i - 1;
    }
    return result;
}

print reverse_string("Hello");  // "olleH"

// Check if string contains substring
fn contains(haystack, needle) {
    let hay_len = len(haystack);
    let needle_len = len(needle);
    
    if needle_len > hay_len {
        return false;
    }
    
    let i = 0;
    while i <= hay_len - needle_len {
        let match = true;
        let j = 0;
        while j < needle_len {
            if haystack[i + j] != needle[j] {
                match = false;
            }
            j = j + 1;
        }
        if match {
            return true;
        }
        i = i + 1;
    }
    return false;
}

print contains("Hello, World!", "World");  // true
print contains("Hello, World!", "Goodbye");  // false

Enhanced For Loops

Our for loop already works with lists. Let's see more patterns.

Iterating with Index

fn for_each_with_index(list, action) {
    let i = 0;
    for item in list {
        action(item, i);
        i = i + 1;
    }
}

let items = ["a", "b", "c"];
for_each_with_index(items, fn(item, idx) {
    print str(idx) + ": " + item;
});
// Output:
// 0: a
// 1: b
// 2: c

Nested Iteration

let matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];

for row in matrix {
    for cell in row {
        print cell;
    }
}
// Output: 1 2 3 4 5 6 7 8 9

Early Exit Pattern

fn find_in_nested(lists, target) {
    for list in lists {
        for item in list {
            if item == target {
                return true;
            }
        }
    }
    return false;
}

let data = [[1, 2], [3, 4], [5, 6]];
print find_in_nested(data, 4);  // true
print find_in_nested(data, 7);  // false

Practical Examples

Example 1: FizzBuzz

fn fizzbuzz(n) {
    let i = 1;
    while i <= n {
        if i % 15 == 0 {
            print "FizzBuzz";
        } else if i % 3 == 0 {
            print "Fizz";
        } else if i % 5 == 0 {
            print "Buzz";
        } else {
            print i;
        }
        i = i + 1;
    }
}

fizzbuzz(15);

Example 2: Prime Numbers

fn is_prime(n) {
    if n <= 1 {
        return false;
    }
    if n == 2 {
        return true;
    }
    if n % 2 == 0 {
        return false;
    }
    
    let i = 3;
    while i * i <= n {
        if n % i == 0 {
            return false;
        }
        i = i + 2;
    }
    return true;
}

fn primes_up_to(max) {
    let result = [];
    let n = 2;
    while n <= max {
        if is_prime(n) {
            push(result, n);
        }
        n = n + 1;
    }
    return result;
}

print primes_up_to(50);
// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Example 3: Sorting (Bubble Sort)

fn bubble_sort(list) {
    let n = len(list);
    let swapped = true;
    
    while swapped {
        swapped = false;
        let i = 1;
        while i < n {
            if list[i - 1] > list[i] {
                // Swap (requires list indexing assignment - not yet implemented)
                // For now, we'd need to rebuild the list
                swapped = true;
            }
            i = i + 1;
        }
    }
    
    return list;
}

// Note: Without index assignment (list[i] = value), we can't modify lists in place
// This would require extending our language - see "What's Next" section

Example 4: Word Count

fn word_count(text) {
    // Split on spaces (simplified)
    let words = [];
    let current = "";
    let i = 0;
    
    while i < len(text) {
        let char = text[i];
        if char == " " {
            if len(current) > 0 {
                push(words, current);
                current = "";
            }
        } else {
            current = current + char;
        }
        i = i + 1;
    }
    
    if len(current) > 0 {
        push(words, current);
    }
    
    return len(words);
}

print word_count("The quick brown fox jumps");  // 5

Example 5: Calculator

fn calculate() {
    print "Simple Calculator";
    print "Enter first number:";
    let a = num(input(""));
    
    print "Enter operator (+, -, *, /):";
    let op = input("");
    
    print "Enter second number:";
    let b = num(input(""));
    
    if op == "+" {
        print "Result: " + str(a + b);
    } else if op == "-" {
        print "Result: " + str(a - b);
    } else if op == "*" {
        print "Result: " + str(a * b);
    } else if op == "/" {
        if b == 0 {
            print "Error: Division by zero";
        } else {
            print "Result: " + str(a / b);
        }
    } else {
        print "Error: Unknown operator";
    }
}

// Uncomment to run:
// calculate();

Type Checking Utilities

fn is_number(value) {
    return type(value) == "number";
}

fn is_string(value) {
    return type(value) == "string";
}

fn is_bool(value) {
    return type(value) == "bool";
}

fn is_list(value) {
    return type(value) == "list";
}

fn is_function(value) {
    return type(value) == "function";
}

fn is_nil(value) {
    return type(value) == "nil";
}

// Usage
print is_number(42);       // true
print is_string("hello");  // true
print is_list([1, 2, 3]);  // true

Standard Library Pattern

Build a "standard library" of utilities:

// math.lux
fn max(a, b) {
    if a > b {
        return a;
    }
    return b;
}

fn min(a, b) {
    if a < b {
        return a;
    }
    return b;
}

fn abs(n) {
    if n < 0 {
        return -n;
    }
    return n;
}

fn clamp(value, low, high) {
    return min(high, max(low, value));
}

print clamp(5, 0, 10);   // 5
print clamp(-5, 0, 10);  // 0
print clamp(15, 0, 10);  // 10

Features Not Yet Implemented

Some features would require language extensions:

1. List Index Assignment

// Desired:
let list = [1, 2, 3];
list[0] = 10;  // Not yet supported

// Workaround: rebuild list
fn set_index(list, index, value) {
    let result = [];
    let i = 0;
    while i < len(list) {
        if i == index {
            push(result, value);
        } else {
            push(result, list[i]);
        }
        i = i + 1;
    }
    return result;
}

2. String Slicing

// Desired:
let word = "Hello";
print word[1:4];  // "ell"

// Workaround: manual extraction
fn slice_string(s, start, end) {
    let result = "";
    let i = start;
    while i < end and i < len(s) {
        result = result + s[i];
        i = i + 1;
    }
    return result;
}

3. Break and Continue

// Desired:
while true {
    let x = num(input("Enter number: "));
    if x == 0 {
        break;  // Not yet supported
    }
    print x * 2;
}

// Workaround: use flags
let running = true;
while running {
    let x = num(input("Enter number: "));
    if x == 0 {
        running = false;
    } else {
        print x * 2;
    }
}

These features are implemented in Chapter 10 "What's Next".

Performance Tips

1. Avoid Rebuilding Strings in Loops

// ❌ Slow: creates new string each iteration
let result = "";
let i = 0;
while i < 1000 {
    result = result + "x";  // Creates new string 1000 times
    i = i + 1;
}

// ✅ Better: use list then join (if you had join as native function)
let parts = [];
let i = 0;
while i < 1000 {
    push(parts, "x");  // Just adds to list
    i = i + 1;
}
// Then join would combine efficiently

2. Minimize Closure Allocations

// ❌ Creates closure every call
fn process_items(items) {
    for item in items {
        apply(item, fn(x) { return x * 2; });  // New closure each iteration
    }
}

// ✅ Define closure once
fn process_items(items) {
    fn double(x) { return x * 2; }
    for item in items {
        apply(item, double);  // Reuse same function
    }
}

Summary

Lux now supports:

FeatureDescription
ListsDynamic arrays with push/pop
List iterationFor loops over lists
List operationsMap, filter, reduce via functions
StringsImmutable character sequences
String concatenation+ operator
String indexingstr[i]
Type checkingtype() function
User inputinput() function

What's Next?

We have a powerful language! But error messages could be better. Let's add comprehensive error handling.

→ Continue to Chapter 7: Error Handling