Topaz Syntax Fundamentals

Master the syntax of Topaz, the language where code becomes poetry. Learn to write beautiful code with modern, expressive syntax designed for maximum clarity.

"The language where code becomes poetry" - Topaz syntax pursues maximum expressiveness with minimal code. Master Topaz's beautiful syntax in this comprehensive guide. 🌟

🎯 Core Philosophy

"Write Less, Express More"

Even complex logic can be expressed concisely and readably.

Global Syntax, Local Expression

  • Keywords: Unified in English (function, let, match, case)
  • Identifiers: Free use of any language, English, Unicode, and even emojis

Everything is an Expression

All constructs like if, match, for, try return values.

📝 Basic Syntax

Variable Declaration

// Immutable variables (default)
let name = "Alice"
let age = 25
let isActive = true

// Mutable variables
mut let score = 85
score = 90  // Can be changed

// Type annotation (optional)
let distance: float = 3.14
let users: Array<string> = ["John", "Jane"]

Null‑Coalescing Assignment (??=)

Statement‑only operator that initializes when the target is None/null.

let mut name: Option<string> = None
name ??= Some("guest")     // now Some("guest")

Function Definition

// Basic function
function greet(name: string) -> string {
    "Hello, {name}!"
}

// Default parameters
function calculate(x: int, y: int = 10) -> int {
    x + y
}

// Multiple return values
function getCoordinates() -> (int, int) {
    (100, 200)
}

// Higher-order functions
function transform(data: Array<int>, fn: (int) -> int) -> Array<int> {
    data.map(fn)
}

Conditionals

// if expression (returns a value)
let message = if age >= 20 {
    "You are an adult"
} else if age >= 13 {
    "You are a teenager"
} else {
    "You are a child"
}

// Ternary-style
let status = if online { "Connected" } else { "Offline" }

Pattern Matching

// Basic matching
let result = match value {
    case 1 => "One"
    case 2 => "Two"
    case 3 => "Three"
    case _ => "Other"
}

// Range matching
let grade = match score {
    case 90..100 => "A"
    case 80..<90 => "B"
    case 70..<80 => "C"
    case _ => "F"
}

// Structural matching
let discount = match customer {
    case { tier: "VIP", amount } if amount > 1000000 => 0.3
    case { tier: "VIP" } => 0.2
    case { joinDate } if today - joinDate > 365.days => 0.1
    case _ => 0.0
}

#### List Patterns

```rust
match xs {
  case [head, ..tail] => useHead(head, tail)
  case [..init, last] => useLast(init, last)
  case [a, .., z] => useEnds(a, z)
  case [x, y, ..rest] if rest.length > 0 => handle(x, y, rest)
}

End‑to‑end example (guard + nested list pattern):

let desc = match numbers {
  case [] => "empty"
  case [single] => "single"
  case [first, .., last] if first < last => "ascending edge"
  case [first, ..mid, last] => "edges {first}..{last}, mid={mid.length}"
}
## 🌊 Pipeline Operations

### Basic Pipeline

```rust
// Data flows like poetry
let result = rawData
    |> normalize()
    |> filter(x => x > 0)
    |> map(x => x * 2)
    |> sort()

Mixed with Method Chaining

let processedString = "hello world"
    .split(" ")
    |> each(word => word.capitalize())
    .join(" ")
    |> append("!", _)
// Result: "Hello World!"

Pipe Sugar

v4

Use concise sugar on the right side of a pipe:

value
  |> .length                  // property sugar: (x => x.length)
  |> replace("foo", _, "bar") // method sugar: (x => replace("foo", x, "bar"))

// Multiple placeholders bind left-to-right within the nearest call
value |> format("id=", _, ":", _)

🧠 Type System

Type Inference

// Types are automatically inferred
let number = 42              // int
let text = "hello"           // string
let array = [1, 2, 3, 4]     // Array<int>
let object = {               // { name: string, age: int }
    name: "Alice",
    age: 25
}

Literal Types

// Restrict types to exact values
type TrafficLight = "red" | "yellow" | "green"
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6
type StatusCode = 200 | 404 | 500

function handleSignal(color: TrafficLight) {
    match color {
        case "red" => stop()
        case "yellow" => caution()
        case "green" => go()
        // Compiler ensures all cases are handled!
    }
}

Union Types

type UserInput = string | int | null

function process(input: UserInput) -> string {
    match input {
        case s: string => "String: {s}"
        case n: int => "Number: {n}"
        case null => "No input"
    }
}

🔁 Loops

for Loops (Expressions)

// Range iteration
for i in 1..10 {
    print("Number: {i}")
}

// Array iteration
for item in ["apple", "banana", "cherry"] {
    print("Fruit: {item}")
}

// With index
for (index, value) in data.enumerate() {
    print("{index}: {value}")
}

// for returns values too!
let squares = for x in 1..5 { x * x }  // [1, 4, 9, 16]

Range step with by

v4
// Step forward
for i in 0..10 by 2 { print(i) }       // 0,2,4,6,8,10

// Step backward with negative stride
for i in 10..0 by -3 { print(i) }      // 10,7,4,1

// Date/Time step (library-defined durations)
for day in startDate..endDate by 1.day { schedule.add(day) }

while Loops

mut let counter = 0
while counter < 10 {
    print("Counter: {counter}")
    counter = counter + 1
}

📚 Collections

Arrays

// Basic arrays
let numbers = [1, 2, 3, 4, 5]
let fruits = ["apple", "banana", "cherry"]

// Array methods
let large = numbers.filter(x => x > 2)   // [3, 4, 5]
let squares = numbers.map(x => x * x)    // [1, 4, 9, 16, 25]
let sum = numbers.reduce(0, +)           // 15

Membership (in)

// Arrays/Lists/Sets
let ok1 = 3 in [1, 2, 3]
let ok2 = "a" in Set.of("a", "b")

// Map keys
let hasId = "id" in userMap.keys

// Ranges
let inside = 5 in 1..10
let outside = 10 in 1..<10

Objects/Structs

// Object literal
let user = {
    name: "Alice",
    age: 25,
    email: "alice@example.com"
}

// Struct definition
struct User {
    name: string,
    age: int,
    email: string
}

// Struct instance
let newUser = User {
    name: "Bob",
    age: 30,
    email: "bob@example.com"
}

Record Update Literal

v4

Shallow‑copy a record and update selected fields immutably.

let user = { name: "Alice", age: 20, city: "Seoul" }
let updated = user{ age: user.age + 1, city: "Busan" }
// { name: "Alice", age: 21, city: "Busan" }

🎭 String Templates

Basic Interpolation

let name = "Alice"
let age = 25
let greeting = "Hello, {name}! You are {age} years old."

Tagged Templates

v4

Standardized tags with safety and meta preservation:

let path = p"/home/{user}/docs/{fileName}"         // path normalization
let pattern = r"^[a-z0-9_]+$"                       // regex with light escapes
let cmd = sh"grep {pattern} {file}"                 // safe shell template (execution policy‑controlled)

// SQL: parameters are always bound (no raw string insertion)
let query = sql"SELECT * FROM users WHERE age > {age} AND city = {city}"

⚡ Async Processing

Automatic Async

// I/O is automatically async but written like sync!
function getUserInfo(id: int) -> User {
    let basicInfo = API.fetchUser(id)      // implicit async handling
    let profile = API.fetchProfile(id)     // implicit async handling
    
    User {
        basicInfo: basicInfo,
        profile: profile
    }
}

Parallel Execution

// Run multiple tasks in parallel
let results = concurrent {
    weather: WeatherAPI.current("NYC"),
    rate: CurrencyAPI.usdRate(),
    news: NewsAPI.headlines(5)
}

🛡️ Error Handling

Result Type

function safeDivide(a: int, b: int) -> Result<int, string> {
    if b == 0 {
        Err("Cannot divide by zero")
    } else {
        Ok(a / b)
    }
}

// Simple with ? operator
function complexCalculation(x: int) -> Result<int, string> {
    let result1 = safeDivide(x, 2)?
    let result2 = safeDivide(result1, 3)?
    Ok(result2 * 10)
}

try Expression

let config = try {
    readFile("config.json")?
} else {
    // Return default value
    { theme: "dark", language: "english" }
}

🎨 Advanced Features

Partial Application

let add10 = add(10, _)
let result = [1, 2, 3].map(add10)  // [11, 12, 13]

Option‑Safe Optional Chaining (?.)

v4

Use ?. only when the left side is Option<T> or a nullable union (e.g., T | null). It desugars to Option.map/flatMap and short‑circuits left‑to‑right.

let user: Option<{ name: string, profile: Option<{ city: string }> }> =
    Some({ name: "Ann", profile: Some({ city: "Seoul" }) })

// Each hop returns Option<...>
let nameOpt = user?.name
let cityOpt = user?.profile?.city

// Combine with ?? for defaults
let city = user?.profile?.city ?? "Unknown"

// Not generic object chaining; use `.` for non‑Option values
let plain = { name: "Jo" }
let ok = plain.name        // use .

Equivalence with map/flatMap:

// user?.profile?.city
let viaFns = user
  |> Option.flatMap(_, u => u.profile)
  |> Option.map(_, p => p.city)

Macros

// Repeat execution macro
macro repeatExecution(times: int) {
    for i in 1..times {
        print("Execution {i}/{times}")
        yield  // Execute user code
    }
}

repeatExecution(3) {
    importantTask()
}

�� Practical Examples

Web API Call

let userData = fetch("https://api.example.com/users/1")
    |> json()
    |> (data => {
        name: data.name,
        email: data.email,
        joinDate: Date.parse(data.created_at)
    })

Data Processing Pipeline

let analysisResult = CSV.read("sales.csv")
    |> filter(row => row.revenue > 1000000)
    |> groupBy(row => row.region)
    |> aggregate(group => {
        region: group.key,
        totalRevenue: group.values.sum(row => row.revenue),
        avgRevenue: group.values.average(row => row.revenue)
    })
    |> sortBy(descending: row => row.totalRevenue)

🎯 Next Steps

You've now mastered Topaz's basic syntax! What to learn next:

Continue your journey where coding becomes poetry with Topaz!