Skip to content

Chapter 14: Standard Library ​

What's Included ​

Wyn's standard library gives you the tools to build real applications without external dependencies. It's not as large as Python's or as comprehensive as Rust's, but it covers the essentials.

This chapter is a tour of what's available. For complete API documentation, see Appendix B.

String Operations ​

You've seen basic string methods. Here's the full set:

Inspection ​

wyn
var text = "Hello, World!"

text.len()                    // 13
text.is_empty()               // false
text.contains("World")        // true
text.starts_with("Hello")     // true
text.ends_with("!")           // true

Transformation ​

wyn
var text = "  Hello  "

text.trim()          // "Hello"
text.trim_left()     // "Hello  "
text.trim_right()    // "  Hello"
text.upper()         // "  HELLO  "
text.lower()         // "  hello  "
text.reverse()       // "  olleH  "

Searching ​

Index methods return the position, or -1 if not found:

wyn
var text = "Hello, World!"

text.index_of("o")           // 4
text.last_index_of("o")      // 8
text.index_of("xyz")         // -1

Splitting and Joining ​

wyn
var text = "apple,banana,cherry"

var parts = text.split(",")  // ["apple", "banana", "cherry"]

var joined = parts.join(" - ")  // "apple - banana - cherry"

Substring ​

wyn
var text = "Hello, World!"

text.substring(0, 5)    // "Hello"
text.substring(7)       // "World!"

Replacement ​

wyn
var text = "Hello, World!"

text.replace("World", "Wyn")     // "Hello, Wyn!"
text.replace_all("l", "L")       // "HeLLo, WorLd!"

Parsing ​

wyn
var num_str = "42"
var float_str = "3.14"

num_str.to_int()        // 42
float_str.to_float()    // 3.14
"abc".to_int()          // 0 (unparseable -> 0)

Unparseable strings convert to 0-validate with is_numeric() first when you need to tell "0" apart from garbage.

File I/O ​

File operations live in the File namespace. File::read returns the contents as a string (empty if the file is missing), so guard with File::exists:

Reading Files ​

wyn
fn main() -> int {
    if (not File::exists("data.txt")) {
        print("data.txt not found")
        return 1
    }
    
    var contents = File::read("data.txt")
    print("File contents:")
    print(contents)
    
    return 0
}

Writing Files ​

wyn
fn main() -> int {
    var data = "Hello, file!"
    var ok = File::write("output.txt", data)
    
    if (ok == 1) {
        print("File written")
    } else {
        print("Error writing file")
    }
    
    return 0
}

File::write returns 1 on success, 0 on failure.

Appending to Files ​

wyn
fn main() -> int {
    var ok = File::append("log.txt", "New log entry\n")
    
    if (ok == 1) {
        print("Appended")
    } else {
        print("Error appending")
    }
    
    return 0
}

File Metadata ​

wyn
fn main() -> int {
    if (File::exists("data.txt")) {
        print("File exists")
        
        var size = File::size("data.txt")
        print("Size: ${size}")
    }
    
    return 0
}

Directory Operations ​

wyn
fn main() -> int {
    // List files in directory
    var files = Dir::list(".")
    for (var i = 0; i < files.len(); i = i + 1) {
        print(files[i])
    }
    
    // Create directory
    Dir::create("new_folder")
    
    // Remove directory
    Dir::remove("old_folder")
    
    return 0
}

Networking ​

HTTP Client ​

Http.get returns the response body as a string (empty on failure):

wyn
fn main() -> int {
    var body = Http.get("https://api.example.com/data")
    
    if (body.len() > 0) {
        print("Body: " + body)
    } else {
        print("Request failed")
    }
    
    return 0
}

HTTP POST ​

wyn
fn main() -> int {
    var data = json_new()
    json_set_string(data, "name", "Alice")
    json_set_int(data, "age", 30)

    var body = Http.post("https://api.example.com/users", json_stringify(data))
    
    print("Created: " + body)
    
    return 0
}

HTTP Server ​

Http.serve(port) starts a server; Http.accept blocks until a request arrives and returns it as a method|path|headers|fd string:

wyn
fn main() -> int {
    var server = Http.serve(8080)
    print("Server running on http://localhost:8080")
    
    while (true) {
        var req = Http.accept(server)
        var path = Http.path(req)
        var fd = Http.fd(req)
        
        if (path == "/") {
            Http.respond(fd, 200, "text/plain", "Hello, World!")
        } else {
            Http.respond(fd, 404, "text/plain", "Not Found")
        }
    }
    
    return 0
}

JSON ​

Parsing JSON ​

json_parse returns a JSON document. Read fields out of it with the typed accessors json_get_string and json_get_int (indexing a parsed document with json["name"] is a type error):

wyn
fn main() -> int {
    var json_str = "{\"name\": \"Alice\", \"age\": 30}"
    var json = json_parse(json_str)
    
    print(json_get_string(json, "name"))  // Alice
    print(json_get_int(json, "age"))      // 30
    
    return 0
}

Generating JSON ​

Build a document with json_new and the json_set_* setters, then serialize it with json_stringify:

wyn
fn main() -> int {
    var data = json_new()
    json_set_string(data, "name", "Alice")
    json_set_string(data, "role", "admin")
    
    var json_str = json_stringify(data)
    print(json_str)  // {"name": "Alice", "role": "admin"}
    
    return 0
}

Time and Date ​

Current Time ​

wyn
fn main() -> int {
    var now = Time::now()
    print("Current timestamp: ${now}")
    
    return 0
}

Formatting Time ​

Time::format(timestamp) renders a timestamp as YYYY-MM-DD HH:MM:SS in local time. For a custom layout, use DateTime::format(timestamp, fmt) with a strftime pattern:

wyn
fn main() -> int {
    var ts = 1739106000
    print(Time::format(ts))              // 2025-02-09 17:00:00
    print(DateTime::format(ts, "%Y-%m-%d"))  // 2025-02-09
    
    return 0
}

Time Arithmetic ​

Timestamps are seconds since the epoch-plain integers, so plain arithmetic works:

wyn
fn main() -> int {
    var now = Time::now()
    var tomorrow = now + 86400   // Add 24 hours (in seconds)
    var yesterday = now - 86400
    print(tomorrow - yesterday)  // 172800
    
    return 0
}

Sleep ​

wyn
fn main() -> int {
    print("Starting...")
    sleep(1000)  // Sleep for 1000ms (1 second)
    print("Done!")
    
    return 0
}

System Operations ​

Command-Line Arguments ​

wyn
fn main() -> int {
    var args = System::args()
    
    print("Program name: " + args[0])
    
    for (var i = 1; i < args.len(); i = i + 1) {
        print("Arg ${i}: ${args[i]}")
    }
    
    return 0
}

Environment Variables ​

Env::get returns the value, or an empty string if the variable isn't set:

wyn
fn main() -> int {
    var home = Env::get("HOME")
    if (home.len() > 0) {
        print("Home: " + home)
    } else {
        print("HOME not set")
    }
    
    Env::set("MY_VAR", "my_value")
    
    return 0
}

Process Execution ​

System::exec returns the command's output; System::exec_code returns its exit code:

wyn
fn main() -> int {
    var output = System::exec("ls -la")
    print("Output: " + output)
    
    var code = System::exec_code("ls -la")
    print("Exit code: ${code}")
    
    return 0
}

Exit Codes ​

wyn
fn main() -> int {
    var fatal = File::exists("panic.flag")
    if (fatal) {
        print("Fatal error")
        return 1  // Non-zero indicates error
    }
    
    return 0  // Success
}

Math Operations ​

Basic Math ​

wyn
fn main() -> int {
    var x = 16.0
    
    print(Math::sqrt(x))        // 4.0
    print(Math::pow(2.0, 8.0))  // 256.0
    print(abs(-42))             // 42
    print(min(5, 3))            // 3
    print(max(5, 3))            // 5
    
    return 0
}

Trigonometry ​

wyn
fn main() -> int {
    print(Math::sin(Math::PI / 2.0))   // 1.0
    print(Math::cos(0.0))              // 1.0
    print(Math::tan(Math::PI / 4.0))   // 1.0
    
    return 0
}

Random Numbers ​

wyn
fn main() -> int {
    // Random integer between 0 and 99
    var rand_int = random_int(0, 100)
    print(rand_int)
    
    // Random float between 0.0 and 1.0
    var rand_float = random_float()
    print(rand_float)
    
    return 0
}

Putting It Together: Real Examples ​

Log File Parser ​

wyn
fn count_errors(path: string) -> Result<int, string> {
    if (not File::exists(path)) {
        return Err("file not found: " + path)
    }
    
    var contents = File::read(path)
    var lines = contents.split("\n")
    var errors = 0
    
    for (var i = 0; i < lines.len(); i = i + 1) {
        if (lines[i].contains("ERROR")) {
            errors = errors + 1
        }
    }
    
    return Ok(errors)
}

fn main() -> int {
    var result = count_errors("app.log")
    
    match result {
        Ok(count) => print("Errors: ${count}"),
        Err(msg) => print("Error: " + msg)
    }
    
    return 0
}

REST API Client ​

json_get_int can be used anywhere. For string fields, wrap the call in a "${...}" interpolation so the result is captured as an owned string variable before you store it in a struct:

wyn
struct User {
    id: int,
    name: string,
    email: string
}

fn main() -> int {
    var body = Http.get("https://api.example.com/users/1")
    
    if (body.len() == 0) {
        print("request failed")
        return 1
    }
    
    var json = json_parse(body)
    
    var name = "${json_get_string(json, 'name')}"
    var email = "${json_get_string(json, 'email')}"
    var user = User {
        id: json_get_int(json, "id"),
        name: name,
        email: email
    }
    
    print("User: " + user.name)
    print("Email: " + user.email)
    
    return 0
}

Configuration Manager ​

wyn
struct Config {
    host: string,
    port: int
}

fn save_config(path: string, config: Config) -> int {
    var data = json_new()
    json_set_string(data, "host", config.host)
    json_set_int(data, "port", config.port)
    
    return File::write(path, json_stringify(data))
}

fn main() -> int {
    var path = "config.json"
    
    // Write defaults the first time the program runs.
    if (not File::exists(path)) {
        print("No config found, writing defaults")
        var defaults = Config { host: "localhost", port: 8080 }
        save_config(path, defaults)
    }
    
    var contents = File::read(path)
    var json = json_parse(contents)
    
    var host = "${json_get_string(json, 'host')}"
    var config = Config {
        host: host,
        port: json_get_int(json, "port")
    }
    
    print("Host: " + config.host)
    print("Port: ${config.port}")
    
    return 0
}

What You've Learned ​

Wyn's standard library covers strings, files, networking, JSON, time, and system operations. It's enough to build real applications without external dependencies.

I/O primitives signal failure with simple values-empty strings, 0/1 status codes-so guard with checks like File::exists and wrap them in your own Result-returning functions for clean error handling with match and ?.

The library is designed for simplicity. Functions do one thing well. Types are straightforward. Error messages are clear.

For complete API documentation, see Appendix B.

Data Persistence ​

Save and load HashMaps as JSON files:

wyn
fn main() -> int {
    // Save state
    var data = { "name": "Alice", "score": "100" }
    Data.save("state.json", data)

    // Load state (returns empty HashMap if file missing)
    var loaded = Data.load("state.json")
    println(loaded.get("name"))   // Alice
    println(loaded.get("score"))  // 100
    return 0
}

Exercises ​

  1. File processor: Read a text file, count words, lines, and characters. Write results to another file.

  2. HTTP client: Fetch data from a public API, parse the JSON, and display specific fields.

  3. Log analyzer: Parse a log file, count different log levels (INFO, WARN, ERROR), and generate a summary.

  4. Config manager: Create a program that loads configuration from a JSON file, with fallback to defaults if the file doesn't exist.

  5. Simple web server: Create an HTTP server that serves static files from a directory.

  6. Command-line tool: Build a CLI tool that accepts arguments and performs different actions based on them.

  7. Data pipeline: Read CSV data, transform it, and write JSON output.


Next: Chapter 15: Real-World Applications

MIT License - v1.22.0