Your First Program
Let’s write your first Shape program and build intuition for expression-oriented, typed data code.
Hello, Shape
Section titled “Hello, Shape”print("Hello, Shape")Example 1: Vectors and Indexing
Section titled “Example 1: Vectors and Indexing”Arrays are indexed with [i], starting at 0. The runtime rejects out-of-bounds reads with Index N out of bounds (length M).
let values = [20, 21, 19, 24, 22]
print(values[0]) // firstprint(values[values.len() - 1]) // lastExample 2: Simple Statistics
Section titled “Example 2: Simple Statistics”let samples = [10.0, 12.0, 11.0, 14.0, 13.0, 12.0]
let total = samples.sum()let count = samples.len()let avg = total / count
print(f"count={count}, total={total}, avg={avg}")Example 3: Filtering and Transformation
Section titled “Example 3: Filtering and Transformation”let readings = [18, 22, 27, 19, 30, 25]
let threshold = 24let high = readings.filter(|v| v > threshold)
print(high) // [27, 30, 25]Example 4: Functions with fn
Section titled “Example 4: Functions with fn”fn is_anomaly(value: number, mean: number, std: number) -> bool { value > (mean + 2 * std)}
let series = [20.1, 20.4, 21.0, 20.3, 25.8]let total = series.sum()let mean = total / series.len()let latest = series[series.len() - 1]// Approximate std for the example; for real code, use std::core::math::std.let approx_std = 1.0
if is_anomaly(latest, mean, approx_std) { print("anomaly detected")} else { print("normal")}Example 5: Match as an Expression
Section titled “Example 5: Match as an Expression”fn bucket(n: int) -> string { match n { x: int where x < 0 => "negative" x: int where x == 0 => "zero" _ => "positive" }}
print(bucket(-3))print(bucket(0))print(bucket(8))Example 6: Typed Records
Section titled “Example 6: Typed Records”Shape requires typed records (declared with type) for field assignment and structural access. Anonymous object literals ({ x: 1, y: 2 }) are read-only — they cannot grow new fields at runtime.
type Record { id: int, label: string, score: int,}
let mut record = Record { id: 42, label: "alpha", score: 0 }record.score = 99
print(f"{record.label}: {record.score}")Save and Run a Script
Section titled “Save and Run a Script”Create analysis.shape:
fn summarize(values: Vec<number>) -> string { let count = values.len() let total = values.sum() let avg = total / count f"count={count}, total={total}, avg={avg}"}
fn main() { let values = [3.2, 4.1, 3.8, 5.0, 4.4] print(summarize(values))}
main()Run it:
shape run analysis.shapeExpected output:
count=5, total=20.5, avg=4.1Key Takeaways
Section titled “Key Takeaways”- Shape is expression-oriented.
fnis the function declaration syntax.- Types are inferred where possible, and required at function boundaries.
- Vectors, typed records, and pattern matching compose naturally.
Next Steps
Section titled “Next Steps”Continue to Basic Concepts.