All functions that take a value as their first argument support both free-function and method syntax via UFCS (Uniform Function Call Syntax):
trim(s)ands.trim()are equivalent.
print("hello")
print(42)
print(true)
Prints a value to stdout followed by a newline. Accepts any type.
let name = read_line()
print("Hello, {name}!")
Reads a line of text from stdin. Returns the input as a string (without trailing newline).
let contents = read_file("data.txt")
print(contents)
Reads the entire contents of a file and returns it as a string. The path is relative to the current working directory.
write_file("output.txt", "Hello, file!")
let data = "line1\nline2\nline3"
write_file("lines.txt", data)
Writes a string to a file, creating the file if it does not exist or overwriting it if it does.
The plain read_file / write_file builtins above panic (abort the process) on any I/O failure — missing file, permission denied, bad path, disk full, etc. That's convenient for scripts and prototypes, but in production code you almost always want to handle errors explicitly.
For that, use the try_ variants, which return a Result:
try_read_file(path: str) -> str ! str—ok(contents)on success,err(message)on any failure.try_write_file(path: str, content: str) -> bool ! str—ok(true)on success,err(message)on any failure.
Pattern match to handle both cases:
fn main() {
let r = try_read_file("config.toml")
match r {
ok(s) => print("loaded {len(s)} bytes")
err(e) => print("could not read config: {e}")
}
}
Rule of thumb: use read_file / write_file when a missing file is a bug you want to crash on. Use try_read_file / try_write_file when a missing file is a situation you want to recover from — that is, almost always, in real software.
let output = exec("ls -la")
print(output)
Executes a system command and returns its stdout as a string. Also available as shell_exec. As of v0.8.0, commands containing shell metacharacters (;, |, &, $, etc.) are rejected at runtime to prevent shell injection. The command is tokenized on whitespace and executed directly via execvp -- no shell is involved.
let home = env_get("HOME")
print("Home directory: {home}")
Returns the value of an environment variable as a string. Returns an empty string if the variable is not set.
let n = "hello".len() // 5
let n = len("hello") // equivalent
Returns the length of a string in bytes.
let cleaned = " hello ".trim() // "hello"
let cleaned = trim(" hello ") // equivalent
Strips leading and trailing whitespace from a string.
let loud = "hello".upper() // "HELLO"
let loud = upper("hello") // equivalent
Converts all characters in a string to uppercase.
let quiet = "HELLO".lower() // "hello"
let quiet = lower("HELLO") // equivalent
Converts all characters in a string to lowercase.
let parts = "a,b,c".split(",") // ["a", "b", "c"]
let words = split("hello world", " ")
Splits a string by a separator and returns an array of substrings.
let found = "hello world".contains("world") // true
let found = contains("hello world", "xyz") // false
Returns true if the string contains the given substring.
let yes = "https://turbolang.dev".starts_with("https") // true
let yes = starts_with("hello", "he")
Returns true if the string starts with the given prefix.
let yes = "main.tb".ends_with(".tb") // true
let yes = ends_with("photo.png", ".png")
Returns true if the string ends with the given suffix.
let fixed = "hello world".replace("world", "turbo") // "hello turbo"
let fixed = replace("aaa", "a", "b") // "bbb"
Replaces all occurrences of a substring with a replacement string.
let i = "hello".index_of("ll") // 2
let i = "hello".index_of("xyz") // -1
Returns the byte index of the first occurrence of a substring, or -1 if not found.
let ch = "hello".char_at(0) // "h"
let ch = "hello".char_at(4) // "o"
Returns the character at the given byte index as a single-character string.
let stars = "*".repeat(5) // "*****"
let wall = "ab".repeat(3) // "ababab"
Repeats a string n times and returns the result.
let csv = join(["a", "b", "c"], ",") // "a,b,c"
let path = join(["usr", "local", "bin"], "/")
Joins an array of strings with a separator between each element.
let s = to_str(42) // "42"
let s = to_str(true) // "true"
let s = to_str(3.14) // "3.14"
Converts any value to its string representation.
let n = [1, 2, 3].len() // 3
let n = len([10, 20]) // 2
Returns the number of elements in an array.
let mut arr = [1, 2, 3]
arr = arr.push(4) // [1, 2, 3, 4]
arr = push(arr, 5) // [1, 2, 3, 4, 5]
Appends an element to the end of an array. Returns a new array (copy-on-write semantics). Reassign the result to the original variable.
let doubled = [1, 2, 3].map(|x: i64| -> i64 { x * 2 }) // [2, 4, 6]
let names = ["a", "b"].map(|s: str| -> str { s.upper() })
Transforms each element of an array by applying a function, returning a new array of the results.
let big = [1, 2, 3, 4, 5].filter(|x: i64| -> bool { x > 3 }) // [4, 5]
let long = words.filter(|w: str| -> bool { w.len() > 3 })
Returns a new array containing only the elements for which the predicate returns true.
let sum = reduce([1, 2, 3, 4], 0, |acc: i64, x: i64| -> i64 { acc + x }) // 10
let product = reduce([2, 3, 4], 1, |acc: i64, x: i64| -> i64 { acc * x })
Folds an array into a single value by applying a function to an accumulator and each element from left to right.
let a = abs(-42) // 42
let b = abs(10) // 10
Returns the absolute value of an integer.
let smallest = min(3, 7) // 3
let smallest = min(-1, 0) // -1
Returns the smaller of two integer values.
let largest = max(3, 7) // 7
let largest = max(-1, 0) // 0
Returns the larger of two integer values.
let result = pow(2, 10) // 1024
let cubed = pow(3, 3) // 27
Raises a base to an integer exponent and returns the result.
let s = sqrt(144.0) // 12.0
let s = sqrt(2.0) // 1.4142135623730951
Returns the square root of a floating-point number.
Turbo ships two flavors of hash map in v0.8.0: the original str → str
API and a new str → int variant. Both share the same underlying map
object — you pick a variant per call, not per map. A fully generic
HashMap<K, V> is planned post-1.0; until then, if you need a different
value type, stringify/parse at the boundary or wait for the generic
version.
let m = hashmap()
Creates and returns a new, empty hash map.
let m = hashmap()
hashmap_set(m, "name", "Turbo")
hashmap_set(m, "version", "0.3")
Sets a string-valued key-value pair. If the key already exists, its
value is overwritten. Mutates m in place; the return value is unit.
let name = hashmap_get(m, "name") // "Turbo"
Returns the string value associated with the given key. The key must
exist in the map — guard with hashmap_has() if you're not sure.
let mut m = hashmap()
m = hashmap_set_int(m, "count", 1)
m = hashmap_set_int(m, "count", hashmap_get_int(m, "count") + 1)
New in v0.8.0. Stores an integer value under a string key. Returns
the same map so you can chain it idiomatically as
m = hashmap_set_int(m, k, v). Internally shares storage with the
str → str variant — do not mix hashmap_set and hashmap_set_int on
the same key.
let n = hashmap_get_int(m, "count") // 1
let missing = hashmap_get_int(m, "nope") // 0
New in v0.8.0. Returns the integer value associated with the given
key, or 0 if the key is not present. If you need to distinguish a
missing key from a stored 0, guard with hashmap_has() first.
let exists = hashmap_has(m, "name") // true
let missing = hashmap_has(m, "foo") // false
Returns true if the hash map contains the given key. Works for both
hashmap_set and hashmap_set_int entries.
let count = hashmap_len(m) // 2
Returns the number of key-value pairs in the hash map. Also available as hashmap_size.
let keys = hashmap_keys(m) // ["name", "version"]
Returns an array of all keys in the hash map.
hashmap_remove(m, "version")
Removes the key-value pair with the given key from the hash map.
let json = "{\"name\":\"Turbo\",\"version\":\"0.3\"}"
let name = json_get(json, "name") // "Turbo"
Extracts a value from a JSON string by key. Returns the value as a string.
let json = json_stringify("name", "Turbo") // "{\"name\":\"Turbo\"}"
Creates a JSON string containing a single key-value pair.
@derive(Display)
struct Point { x: i64, y: i64 }
let p = Point { x: 1, y: 2 }
let json = to_json(p) // "{\"x\":1,\"y\":2}"
Serializes a struct to a JSON string.
let points = [Point { x: 1, y: 2 }, Point { x: 3, y: 4 }]
let json = to_json_array(points) // "[{\"x\":1,\"y\":2},{\"x\":3,\"y\":4}]"
Serializes an array of structs to a JSON array string.
let body = http_get("https://api.example.com/data")
print(body)
Performs an HTTP GET request and returns the response body as a string.
let response = http_post("https://api.example.com/items", "{\"name\":\"turbo\"}")
print(response)
Performs an HTTP POST request with the given body string and returns the response body as a string.
let app = http_server(8080)
Creates a new HTTP server bound to the given port on 127.0.0.1 (localhost only). The server does not start listening until http_listen is called.
let app = http_server_public(8080)
Creates a new HTTP server bound to the given port on 0.0.0.0 (all interfaces). Use this only when you intentionally want the server accessible from other machines. For production, always put a reverse proxy (nginx, Caddy) in front. See SECURITY.md.
route(app, "GET", "/", |req: str| -> str {
respond_text(200, "Hello, Turbo!")
})
route(app, "POST", "/api/echo", |req: str| -> str {
let body = request_body(req)
respond_text(200, body)
})
Registers a route handler for the given HTTP method and path. The handler receives the request as a string and must return a response string (use respond_text, respond_html, or respond_json to construct it).
let app = http_server(3000)
route(app, "GET", "/", |req: str| -> str { respond_text(200, "ok") })
http_listen(app)
Starts the HTTP server and begins accepting connections. This call blocks until the server is stopped.
let text = respond_text(200, "ok")
let html = respond_html(200, "<!doctype html><html><body>ok</body></html>")
let json = respond_json(200, "{\"status\":\"ok\"}")
Constructs an HTTP response string with the given status code, body, and an explicit content type.
route(app, "POST", "/data", |req: str| -> str {
let body = request_body(req)
respond_text(200, body)
})
Extracts the body from an HTTP request string.
route(app, "GET", "/info", |req: str| -> str {
let method = request_method(req) // "GET"
respond_text(200, method)
})
Returns the HTTP method (GET, POST, PUT, DELETE, etc.) from a request string.
let path = request_path(req) // "/api/users"
Returns the path portion of an HTTP request string.
// For a request to /search?q=turbo
let query = request_query(req, "q") // "turbo"
Extracts the value of a query parameter from an HTTP request string by key.
let content_type = request_header(req, "Content-Type")
let auth = request_header(req, "Authorization")
Returns the value of a named HTTP header from a request string.
let ch = channel()
Creates an unbounded channel for sending and receiving integer values between concurrent tasks.
let ch = channel()
send(ch, 42)
Sends a value into a channel. Does not block (the channel is unbounded).
let value = recv(ch) // blocks until a value is available
print(value)
Receives a value from a channel. Blocks the current task until a value is available.
let m = mutex(0)
Creates a mutex wrapping an initial integer value. Use mutex_get and mutex_set to read and write the value safely across concurrent tasks.
let m = mutex(0)
let value = mutex_get(m) // 0
Acquires the mutex lock and returns the current value.
mutex_set(m, 42)
let value = mutex_get(m) // 42
Acquires the mutex lock and sets the value.
sleep(1000) // sleep for 1 second
sleep(100) // sleep for 100ms
Suspends the current task for the given number of milliseconds.
@derive(Clone)
struct Point { x: i64, y: i64 }
let a = Point { x: 1, y: 2 }
let b = clone(a)
Creates a deep copy of a struct. The struct must have @derive(Clone).
assert(2 + 2 == 4)
assert(x > 0, "x must be positive")
Asserts that a condition is true. Aborts with an error if the condition is false. An optional message can be provided.
assert_eq(add(2, 3), 5)
assert_eq("hello".len(), 5)
Asserts that two values are equal. Aborts with an error showing the expected and actual values if they differ.
assert_ne(a, b)
assert_ne("hello", "world")
Asserts that two values are not equal. Aborts with an error if they are equal.
panic("something went wrong")
panic()
Immediately aborts execution with an error message. If no message is provided, a default message is used. This function never returns.
These functions are only available inside
unsafeblocks. They provide direct memory access and should be used with extreme caution.
unsafe {
let value = deref(addr)
}
Reads and returns the 64-bit integer stored at the given memory address.
unsafe {
store(addr, 42)
}
Writes a 64-bit integer value to the given memory address.
| Category | Functions |
|---|---|
| I/O | print, read_line, read_file, write_file, try_read_file, try_write_file |
| Strings | len, trim, upper, lower, split, contains, starts_with, ends_with, replace, index_of, char_at, repeat, join, to_str |
| Arrays | len, push |
| Functional | map, filter, reduce |
| Math | abs, min, max, pow, sqrt |
| HashMap | hashmap, hashmap_set, hashmap_get, hashmap_set_int, hashmap_get_int, hashmap_has, hashmap_len, hashmap_keys, hashmap_remove |
| JSON | json_get, json_stringify, to_json, to_json_array |
| HTTP Client | http_get, http_post |
| HTTP Server | http_server, http_server_public, route, http_listen, respond_text, respond_html, respond_json, request_body, request_method, request_path, request_query, request_header |
| System | exec, env_get |
| Concurrency | channel, send, recv, mutex, mutex_get, mutex_set, sleep, clone |
| Testing | assert, assert_eq, assert_ne, panic |
| Unsafe | deref, store |