Chapter 19: Standard Library Tour

Time: 90 min | Audience: Intermediate | Prerequisites: Chapters 01-06


Learning Outcomes

After this chapter, you will: - Know the major modules and APIs in Zebra's standard library - Understand when to use built-in functions vs. writing your own - Navigate API documentation effectively - Use string, collection, and math operations fluently - Recognize patterns you can apply to your own libraries


Overview: What's Already Built

One of Zebra's strengths is a thoughtfully designed standard library that covers common tasks without being bloated. Before writing utilities or helper functions, check what's already available. This chapter is a tour of the major components.

The standard library is organized into logical modules: - String Operations — manipulation and inspection - Collection Operations — Lists, HashMaps, Sets - Type Conversions — converting between types - Math Operations — numeric functions - System Access — arguments, environment, file paths - I/O Basics — console and file operations


String Operations

Strings are the most commonly used type in real-world programs. Zebra's string API is powerful but focused on the most useful operations.

Basic Properties and Inspection

// file: stdlib-string-inspect.zbr

// teaches: string properties and inspection methods // chapter: 19

def main() var text = "Hello, World!"

// Length println(text.len) # 13

// Check if empty if text.len == 0 println("Empty string")

// Character access var first_char = text.charAt(0) # 'H' var last_char = text.charAt(text.len - 1) # '!' println(first_char) println(last_char)

// Check existence if text.contains("World") println("Found World")

if text.startsWith("Hello") println("Greeting detected")

if text.endsWith("!") println("Exclamation found")

Case Conversion

// file: stdlib-string-case.zbr

// teaches: case conversion methods // chapter: 19

def main() var text = "Zebra Programming"

// Uppercase var upper = text.upper() # "ZEBRA PROGRAMMING" println(upper)

// Lowercase var lower = text.lower() # "zebra programming" println(lower)

// Practical example: case-insensitive comparison def case_insensitive_equals(a as str, b as str) as bool return a.lower() == b.lower()

if case_insensitive_equals("Zebra", "ZEBRA") println("Same language, different case")

String Searching and Replacement

// file: stdlib-string-search.zbr

// teaches: searching and replacing in strings // chapter: 19

def main() var message = "The quick brown fox jumps over the lazy dog"

// Find first occurrence var pos = message.indexOf("fox") # 16 if pos >= 0 println("Found 'fox' at position ${pos}")

// Count occurrences (manual approach) var text = "apple apple apple" var count = 0 var search_pos = 0 while search_pos >= 0 search_pos = text.indexOf("apple", search_pos) if search_pos >= 0 count = count + 1 search_pos = search_pos + 1 println(count) # 3

// Replace first occurrence var replaced = message.replace("fox", "cat") println(replaced) # "The quick brown cat jumps over the lazy dog"

// Replace all occurrences var all_replaced = message.replaceAll("the", "a") println(all_replaced)

String Splitting and Joining

// file: stdlib-string-split-join.zbr

// teaches: splitting and joining strings // chapter: 19

def main() // Split by delimiter var csv_line = "John,25,Engineer,San Francisco" var fields = csv_line.split(",")

// fields is a List(str) println(fields.count()) # 4 println(fields.at(0)) # "John" println(fields.at(1)) # "25"

// Process fields var names = List(str)() for field in fields if field.len > 0 names.add(field)

// Join with separator var rejoined = names.join(" | ") println(rejoined) # "John | 25 | Engineer | San Francisco"

// Multi-character delimiter var text = "apple::orange::banana" var fruits = text.split("::") println(fruits.join(", ")) # "apple, orange, banana"

Whitespace Trimming

// file: stdlib-string-trim.zbr

// teaches: removing whitespace from strings // chapter: 19

def main() var input = " Hello, World! \n"

// Trim both sides var trimmed = input.trim() # "Hello, World!" println("'${trimmed}'")

// Trim left side only var right_padded = " left-trimmed" println("'${right_padded.trimLeft()}'") # "'left-trimmed'"

// Trim right side only var left_padded = "right-trimmed " println("'${left_padded.trimRight()}'") # "'right-trimmed '"

// Practical use: parsing user input def parse_number_from_input(input as str) as int? var trimmed = input.trim() if trimmed.len == 0 return nil return trimmed.toInt()

var num = parse_number_from_input(" 42 ") if num != nil println("Parsed: ${num}")

String Extraction and Concatenation

// file: stdlib-string-extract-concat.zbr

// teaches: substring extraction and string concatenation // chapter: 19

def main() var text = "Hello, World!"

// Extract substring var hello = text.substring(0, 5) # "Hello" var world = text.substring(7, 12) # "World" println(hello) println(world)

// Concatenate strings var greeting = hello.concat(", ").concat(world) println(greeting) # "Hello, World"

// String interpolation (often cleaner) var result = "${hello}, ${world}" println(result)

// Building strings in loops var parts = List(str)() for i in 1.to(5) parts.add("Item-${i}")

var result_str = parts.join(", ") println(result_str) # "Item-1, Item-2, Item-3, Item-4, Item-5"


Collection Operations

Collections are the workhorses of most programs. Zebra provides three main collection types, each with a focused API.

List Operations

Lists are ordered, mutable collections that grow dynamically. They're your go-to for sequences.

// file: stdlib-list-ops.zbr

// teaches: list operations and patterns // chapter: 19

def main() var items = List(str)()

// Add items items.add("apple") items.add("banana") items.add("cherry") println(items.count()) # 3

// Access by index println(items.at(0)) # "apple" println(items.at(2)) # "cherry"

// Check contents if items.contains("banana") println("Found banana")

// Remove specific item items.remove("banana") println(items.count()) # 2

// Iterate over list for fruit in items println("Fruit: ${fruit}")

// Find index of item var pos = items.indexOf("apple") # 0 or -1 if not found if pos >= 0 println("Found at position ${pos}")

// Clear list items.clear() println(items.count()) # 0

HashMap Operations

HashMaps store key-value pairs. Use them when you need to look up values by name or ID.

// file: stdlib-hashmap-ops.zbr

// teaches: hashmap operations and patterns // chapter: 19

def main() var scores = HashMap(str, int)()

// Add key-value pairs scores.put("Alice", 95) scores.put("Bob", 87) scores.put("Charlie", 92)

// Retrieve value var alice_score = scores.fetch("Alice") # 95 if alice_score != nil println("Alice scored: ${alice_score}")

// Check if key exists if scores.contains("Bob") println("Bob's record found")

// Update value scores.put("Bob", 89) # Overwrites previous

// Remove key scores.remove("Charlie")

// Iterate over key-value pairs for key in scores.keys() var value = scores.fetch(key) if value != nil println("${key}: ${value}")

// Get all keys var all_keys = scores.keys() println(all_keys.count()) # 2

Set Operations

Sets store unique items with no duplicates. Use them for membership testing and deduplication.

// file: stdlib-set-ops.zbr

// teaches: set operations for uniqueness // chapter: 19

def main() var visited_cities = Set(str)()

// Add items visited_cities.add("New York") visited_cities.add("London") visited_cities.add("Tokyo")

// Try adding duplicate visited_cities.add("New York") # No-op, already exists println(visited_cities.count()) # 3

// Check membership if visited_cities.contains("Paris") println("Been to Paris") else println("Haven't visited Paris yet")

// Remove item visited_cities.remove("Tokyo")

// Iterate over set for city in visited_cities println("Visited: ${city}")

// Practical: remove duplicates from list var numbers = List(int)() numbers.add(1) numbers.add(2) numbers.add(2) numbers.add(3) numbers.add(3) numbers.add(3)

var unique = Set(int)() for num in numbers unique.add(num)

println(unique.count()) # 3


Type Conversions

Zebra's type system is strict—you'll need to convert between types explicitly. The standard library provides straightforward conversion methods.

String Conversions

// file: stdlib-type-conversions.zbr

// teaches: converting between types and strings // chapter: 19

def main() // String to int var num_str = "42" var num = num_str.toInt() println(num) # 42

// String to float var float_str = "3.14" var float_val = float_str.toFloat() println(float_val) # 3.14

// Int to string var num2 = 100 var str2 = num2.toString() println(str2) # "100"

// Float to string var pi = 3.14159 var pi_str = pi.toString() println(pi_str) # "3.14159"

// Boolean to string var flag = true var flag_str = flag.toString() println(flag_str) # "true"

// Error handling for conversions var user_input = "not a number" var parsed = user_input.toInt() if parsed == nil println("Invalid number")

// Safe conversions with nil checking var value as int? = "123".toInt() if value != nil println("Parsed successfully: ${value}")


Math Operations

Zebra doesn't have a separate "Math" module—arithmetic is built into the language and type system.

// file: stdlib-math-operations.zbr

// teaches: basic math operations in Zebra // chapter: 19

def main() // Arithmetic operators var a = 10 var b = 3

println(a + b) # 13 println(a - b) # 7 println(a * b) # 30 println(a / b) # 3 (integer division) println(a % b) # 1 (modulo/remainder)

// Floating-point math var x = 10.5 var y = 3.2

println(x + y) # 13.7 println(x - y) # 7.3 println(x * y) # 33.6 println(x / y) # ~3.28

// Comparison operators println(a > b) # true println(a < b) # false println(a >= b) # true println(a == b) # false println(a != b) # true

// Logical operators var condition1 = true var condition2 = false

println(condition1 and condition2) # false println(condition1 or condition2) # true println(not condition1) # false

// Common patterns: min/max def min(a as int, b as int) as int if a < b return a else return b

def max(a as int, b as int) as int if a > b return a else return b

println(min(5, 3)) # 3 println(max(5, 3)) # 5

// Absolute value def abs_value(n as int) as int if n < 0 return 0 - n else return n

println(abs_value(-42)) # 42


System Access

Accessing the program's environment, arguments, and current directory is essential for real-world programs.

// file: stdlib-system-access.zbr

// teaches: accessing system information // chapter: 19

def main() // Command-line arguments var args = System.args() println("Argument count: ${args.count()}")

if args.count() > 0 println("First argument: ${args.at(0)}") println("All arguments:") for arg in args println(" - ${arg}")

// Environment variables var home = System.env("HOME") if home != nil println("Home directory: ${home}")

var path = System.env("PATH") if path != nil var dirs = path.split(":") # On Unix; Windows uses ";" println("PATH has ${dirs.count()} directories")

// Get current working directory var cwd = System.cwd() println("Current directory: ${cwd}")

// Practical example: parse arguments def parse_arguments(args as List(str)) as HashMap(str, str)? var options = HashMap(str, str)() var i = 0

while i < args.count() var arg = args.at(i)

if arg.startsWith("--") var key = arg.substring(2, arg.len) var value = ""

if i + 1 < args.count() and not args.at(i + 1).startsWith("--") value = args.at(i + 1) i = i + 1

options.put(key, value)

i = i + 1

return options


Console I/O

Basic console operations are fundamental to interactive programs.

// file: stdlib-console-io.zbr

// teaches: printing to console // chapter: 19

def main() // Simple output print("Hello, ") println("World!") # Adds newline

// Output of different types println(42) println(3.14) println(true)

// String interpolation (covered earlier) var name = "Alice" var age = 30 println("${name} is ${age} years old")

// Formatted output var price = 19.99 println("Price: $${price}")

// Error output (if available) System.errln("This is an error message")

// Practical: status messages def process_items(items as List(str)) for item in items print("Processing ${item}... ") // Do work here println("Done")

var items = List(str)() items.add("file1.txt") items.add("file2.txt") items.add("file3.txt")

process_items(items)


Practical Patterns: Data Processing

Now let's put these pieces together in real scenarios.

// file: stdlib-data-processing.zbr

// teaches: combining stdlib functions for data processing // chapter: 19

def main() // Parse CSV and calculate statistics var data = "Alice,95,Engineering Bob,87,Sales Charlie,92,Engineering Diana,88,Sales"

var lines = data.split("\n") var scores = List(int)() var dept_map = HashMap(str, int)()

for line in lines var parts = line.split(",") if parts.count() == 3 var name = parts.at(0) var score = parts.at(1).toInt() var dept = parts.at(2).trim()

if score != nil scores.add(score)

// Track count by department var current = dept_map.fetch(dept) if current != nil dept_map.put(dept, current + 1) else dept_map.put(dept, 1)

// Calculate average var total = 0 for score in scores total = total + score

var average = total / scores.count() println("Average score: ${average}")

// Report by department println("Departments:") for dept in dept_map.keys() var count = dept_map.fetch(dept) println(" ${dept}: ${count} people")


Key Takeaways

1. Know Your Tools — The standard library covers 80% of common tasks. Check the API before rolling your own.

2. String Operations — Master .split(), .join(), .contains(), .replace() and type conversions—you'll use them constantly.

3. Collections First — Always think: "Should this be a List, HashMap, or Set?" before designing data structures.

4. Explicit Types — Zebra's strict type system means conversions are explicit. That's a feature, not a bug.

5. Read Documentation — This chapter is a tour, not exhaustive. The full API reference is your friend.


Exercises

1. Word Frequency Counter — Read a CSV, split by commas, count unique words with a HashMap 2. Case Converter — Read user input, convert to upper/lower/title case based on command-line flag 3. CSV Validator — Read CSV file, ensure all rows have same number of columns, report errors 4. Text Processor — Read text, remove duplicates, sort alphabetically, print report


What's Next

You now understand what's available in the standard library. Chapter 20 covers extending that capability with file I/O and system access for real-world programs.