import std.string (ToString)
type pub Person {
let @name: String
}
impl ToString for Person {
fn pub to_string -> String {
@name
}
}
Key points:
- Use
impl TraitName for TypeNamesyntax - Traits define interfaces that types can implement
- Standard library traits like
ToStringare commonly used
type pub enum ErrorKind {
case InvalidHeader
case InvalidXRef
case MissingObject
}
impl ToString for ErrorKind {
fn pub to_string -> String {
match self {
case InvalidHeader -> 'Invalid PDF header'
case InvalidXRef -> 'Invalid cross-reference table'
case MissingObject -> 'Missing object'
}
}
}
Key points:
- Enums can implement traits
- Use
match selfinside trait implementations - Single-quoted strings work fine for string literals
# find_map: Find first value that maps to Some
let result = entries.iter.find_map(fn (entry) {
if entry.key == target {
Option.Some(ref entry.value)
} else {
Option.None
}
})
# map: Transform each element
let items = arr.iter.map(fn (obj) { obj.to_string })
# join: Join iterator results with separator
let result = StdString.join(items, with: ' ')
Key points:
.iterreturns an iterator over collectionsfind_mapcombines find and map operations- Iterator methods work well with closures
# Pattern match on nested Option
fn pub get_name(key: String) -> Option[String] {
match get(key) {
case Some(v) -> {
match v {
case Name(name) -> Option.Some(name.clone)
case _ -> Option.None
}
}
case _ -> Option.None
}
}
Key points:
- Use nested pattern matching for complex Option/Result chains
- Return
Option.Some(value)not justvalue - Use
.clone()when returning owned copies
import std.bytes (Bytes, ToSlice)
# Generic function that accepts String, ByteArray, or their Slices
fn example[B: Bytes, S: ToSlice[B]](value: ref S) -> String {
value.to_slice.slice(0, 5).to_string
}
type pub Config {
let @max_errors: Int
let @strict_mode: Bool
fn pub static default -> Config {
Config(max_errors: 100, strict_mode: false)
}
fn pub static strict -> Config {
Config(max_errors: 0, strict_mode: true)
}
fn pub static permissive -> Config {
Config(max_errors: 9999999, strict_mode: false)
}
}
# Usage
let config = Config.default
let strict_config = Config.strict
type pub RequestBuilder {
let mut @method: String
let mut @path: String
let mut @headers: Array[(String, String)]
}
impl RequestBuilder {
fn pub static new -> RequestBuilder {
RequestBuilder(
method: "GET",
path: "/",
headers: [],
)
}
fn pub mut method(method: String) -> mut RequestBuilder {
@method = method
self
}
fn pub mut path(path: String) -> mut RequestBuilder {
@path = path
self
}
fn pub mut header(name: String, value: String) -> mut RequestBuilder {
@headers.push((name, value))
self
}
fn pub build -> Request {
Request(
method: @method,
path: @path,
headers: @headers,
)
}
}
# Usage
let request = RequestBuilder.new
.method("POST")
.path("/api/users")
.header("Content-Type", "application/json")
.build
type pub enum ParseError {
case InvalidSyntax(String)
case UnexpectedToken(String)
case EndOfInput
}
impl ToString for ParseError {
fn pub to_string -> String {
match self {
case InvalidSyntax(msg) -> "Invalid syntax: ${msg}"
case UnexpectedToken(token) -> "Unexpected token: ${token}"
case EndOfInput -> "Unexpected end of input"
}
}
}
import std.sync (Promise)
type async Worker {
let @id: Int
fn async pub compute(data: String, promise: uni Promise[String]) {
let result = process_data(data)
promise.set(result)
}
}
type async Main {
fn async main {
let worker = Worker(id: 1)
let result = await worker.compute("input data")
# Use result
}
}
type pub Connection {
let @handle: Int
let mut @closed: Bool
}
impl Connection {
fn pub static open(path: String) -> Result[Connection, String] {
# Open connection
Result.Ok(Connection(handle: 1, closed: false))
}
fn pub mut close {
if not @closed {
# Close the resource
@closed = true
}
}
}
impl Drop for Connection {
fn mut drop {
close
}
}
type pub enum JsonValue {
case Null
case Bool(Bool)
case Number(Float)
case String(String)
case Array(Array[JsonValue])
case Object(Array[(String, JsonValue)])
}
Use constants for:
- Configuration values (ports, timeouts, buffer sizes)
- Version numbers or API identifiers
- Magic numbers that need meaningful names
- Application-wide settings that never change
let PORT = 3000
let DEFAULT_TIMEOUT = 30
let MAX_RETRIES = 3
let API_VERSION = "v1"