Put any expression inside { } in an f"..." string. Text has methods you call with a dot.
let name = "Tanisha"
let mood = " sunny "
say(f"Hello, {name}! Today feels {mood.trim()}.")
say(name.upper(), name.len(), name.contains("le"))
say("a,b,c".split(","))
Lists keep things in order. Methods like map and filter take a function.
let scores = [7, 10, 4, 9]
say(scores.sort(), scores.sum(), scores.max())
say(scores.filter(fn(s) { return s >= 7 }))
say(scores.map(fn(s) { return s * 10 }))
say(9 in scores)
A map pairs keys with values. Read a field with a dot or with brackets.
let alert = {"ip": "203.0.113.42", "tries": 22}
alert.level = "critical"
alert["tries"] += 1
say(alert)
for key in alert {
say(f"{key} = {alert[key]}")
}
for walks through a list, text or map. break stops early, continue skips ahead.
for n in range(1, 20) {
if n % 2 == 0 {
continue
}
if n > 9 {
break
}
say(f"{n} is odd")
}
Every mistake can be caught. The error has a message, a line number and a kind, so you can catch just the kinds you expect.
import json
try {
json.parse("{not json")
} catch err: ParseError {
say(f"Couldn't read it: {err.message}")
} finally {
say("done")
}
fn check(age) {
if age < 0 { throw "Age can't be negative" }
return age
}
try { check(-1) } catch err { say(err.message) }
Dozens of libraries come built in. import one and use it with a dot.
import hash
import encode
import text
say(hash.sha256("hello").slice(0, 16))
say(encode.base64("Hello from TB"))
say(text.format_number(1234567.5, 1))
A class bundles data and the things you can do with it. extends builds on another class, and super reaches the parent's version.
class Host {
fn init(name, ip) {
self.name = name
self.ip = ip
}
fn text() { return f"{self.name} ({self.ip})" }
}
class Server extends Host {
fn init(name, ip, ports = [22]) {
super.init(name, ip)
self.ports = ports
}
}
let web = Server("web01", "192.0.2.10", [80, 443])
say(web, web.ports, web is Host)
match tries patterns in order. Lists and maps can be taken apart into names, here and in let.
let events = [
{"kind": "login", "user": "Tanisha"},
{"kind": "scan", "ports": [22, 80, 443]},
{"kind": "alert", "level": 9},
]
for e in events {
say(match e {
{"kind": "login", "user": who} => f"{who} logged in"
{"ports": [first, ...rest]} => f"scan from port {first}, {len(rest)} more"
{"level": n} if n > 7 => "urgent alert"
_ => "other"
})
}
let {kind, user = "nobody"} = events[1]
say(kind, user)
A function with yield makes values one at a time. Chain map, filter and take and only the values you need are made.
fn fibonacci() {
let [a, b] = [0, 1]
while true {
yield a
a, b = b, a + b
}
}
say(fibonacci().take(10).to_list())
say(fibonacci().filter(n => n % 2 == 0).take(5).to_list())
for i, n in fibonacci().take(3).enumerate() {
say(f"#{i}: {n}")
}