Types & values
Langoost has a small set of value types. Type annotations are optional, and values are strongly typed at runtime. A lightweight static checker also runs at compile time — see Static type checking below.
Value types
| Type | Description | Example |
|---|---|---|
int | 64-bit signed integer | 42, -7, 0 |
float | 64-bit IEEE-754 double | 3.14, -0.5, 1e10 |
bool | Boolean | true, false |
string | UTF-8 text | "hello", 'world' |
array | Ordered list of any values | [1, "two", true] |
object | Key/value structure | {x: 10, y: 20} |
void | Absence of a value (nil) | nil |
any | Accepts any type, unchecked | — |
json / yaml / xml | String annotated as that data format | {key: "val"} |
Array types use a [] suffix on the element type: int[], string[].
Number literals
Integers can be written in several bases, with _ as a digit separator; floats
support scientific notation:
let dec = 1_000_000
let hex = 0xDEAD_BEEF
let bin = 0b1010
let oct = 0o755
let f = 1.5e-3
Strings
Single and double quotes are both accepted, with escapes \n, \t, \r,
\", \', \\, \0:
let a = "hello"
let b = 'world'
Template strings
Backtick strings interpolate embedded expressions with ${...}:
let name = "Ada"
println(`Hello, ${name} — you have ${3 + 4} messages`)
Objects
Object literals map keys to values. Keys can be read with dot or bracket access; brackets also allow dynamic keys:
let user = {name: "alice", age: 30}
println(user.name) // "alice"
println(user["age"]) // 30
user["role"] = "admin" // add / update a field
Objects double as maps. To attach a named type, see classes & types.
nil and negative indexing
nil is the empty/void value. Arrays and strings support Python-style negative
indices:
let xs = [10, 20, 30]
println(xs[-1]) // 30 (last element)
let missing = nil
Conversion
Coercion is explicit:
let n: int = toInt("42")
let f: float = toFloat(n)
let s: string = toString(n)
println(typeof(n)) // "int"
The json, yaml, and xml types are strings with special meaning — see the
stdlib json module and the : json inline-literal
syntax.
Static type checking
A lightweight, annotation-driven checker runs at compile time. It’s intentionally conservative — it catches obvious mistakes without getting in the way of dynamic code. It currently verifies that literals match their declared type in four places:
let n: int = "oops" // compile error: expected int
fn area(w: float): float {
return "nope" // compile error: expected float
}
let x: T = literalx = literalwhenxis a typed local or globalreturn literalfrom a function with a declared return type- typed parameter defaults
Enforcement covers only the primitive set int, float, string, bool, and
array. Other annotations — json, any, class names, interfaces — pass
through unchecked, so dynamic code keeps working. There is no type inference
across expressions yet.