This is the reference for Seen's syntax and semantics.
let)let name = "Alice"
let age = 30
let pi = 3.14159
var)var count = 0
count = count + 1
val)val MAX_SIZE = 1024
const PI = 3.14159265
static var instance_count = 0
Types can be explicit or inferred:
let x: Int = 42
let y: Float = 3.14
let s: String = "hello"
let b: Bool = true
let c: Char = 'A'
| Type | Description |
|---|---|
Int |
64-bit signed integer |
Float |
64-bit floating point |
Bool |
Boolean (true/false) |
String |
UTF-8 string |
Char |
Unicode code point |
Void |
No value |
Never |
Function never returns |
fun greet(name: String) r: String {
return "Hello, {name}!"
}
The r: syntax specifies the return type.
fun logMessage(msg: String) {
println(msg)
}
For single-expression bodies:
fun double(x: Int) r: Int => x * 2
fun add(a: Int, b: Int) r: Int {
return a + b
}
if x > 0 {
println("positive")
} else {
println("non-positive")
}
let result = if x > 0 { "positive" } else { "non-positive" }
var i = 0
while i < 10 {
println("{i}")
i = i + 1
}
for item in items {
println("{item}")
}
for i in 0..10 {
println("{i}") // 0 through 9
}
for i in 0..=10 {
println("{i}") // 0 through 10
}
loop {
let input = readLine()
if input == "quit" {
break
}
}
for i in 0..100 {
if i == 50 { break }
if i % 2 == 0 { continue }
println("{i}")
}
let result = when value {
is 1 => "one"
is 2 => "two"
is 3 => "three"
else => "other"
}
when shape {
is Circle(r) => println("Circle with radius {r}")
is Rectangle(w, h) => println("Rectangle {w}x{h}")
}
class Point {
var x: Float
var y: Float
static fun new(x: Float, y: Float) r: Point {
return Point { x: x, y: y }
}
fun distanceTo(other: Point) r: Float {
let dx = this.x - other.x
let dy = this.y - other.y
return sqrt(dx * dx + dy * dy)
}
}
Use static fun new(...) by convention:
let p = Point.new(3.0, 4.0)
this keywordInstance methods access fields via this:
fun getX() r: Float {
return this.x
}
class Shape {
var name: String
fun describe() r: String {
return "Shape: {this.name}"
}
}
class Circle extends Shape {
var radius: Float
fun area() r: Float {
return 3.14159 * this.radius * this.radius
}
}
data struct Color(r: Int, g: Int, b: Int)
This is a compact value type declaration.
struct Config {
var width: Int
var height: Int
var title: String
}
enum Direction {
North
South
East
West
}
enum Shape {
Circle(radius: Float)
Rectangle(width: Float, height: Float)
Triangle(base: Float, height: Float)
}
let dir = Direction.North
let shape = Shape.Circle(5.0)
trait Printable {
fun display() r: String
}
impl Printable for Point {
fun display() r: String {
return "({this.x}, {this.y})"
}
}
fun printItem<T: Printable>(item: T) {
println(item.display())
}
fun max<T>(a: T, b: T) r: T {
if a > b { return a }
return b
}
class Stack<T> {
var items: Array<T>
static fun new() r: Stack<T> {
return Stack { items: Array<T>() }
}
fun push(item: T) {
this.items.push(item)
}
fun pop() r: T {
return this.items.pop()
}
fun isEmpty() r: Bool {
return this.items.length() == 0
}
}
fun sort<T: Ord>(arr: Array<T>) r: Array<T> {
// T must implement Ord
}
let doubled = apply(nums, |x| x * 2)
let filtered = items.filter(|x| x > 0)
Closures use |params| expression syntax. Currently no-capture (function pointer) semantics.
T?var name: String? = null
name = "Alice"
?.let len = name?.length() // returns null if name is null
??let displayName = name ?? "Anonymous"
if let n = name {
println("Name is {n}")
}
fun divide(a: Int, b: Int) r: Result<Int, String> {
if b == 0 {
return Err("division by zero")
}
return Ok(a / b)
}
? operatorPropagates errors to the caller:
fun compute() r: Result<Int, String> {
let x = divide(10, 2)?
let y = divide(x, 3)?
return Ok(x + y)
}
try {
let result = riskyOperation()
println("Success: {result}")
} catch e {
println("Error: {e}")
}
Use {expression} inside double-quoted strings:
let name = "World"
println("Hello, {name}!")
let x = 42
println("The answer is {x}")
let p = Point.new(3.0, 4.0)
println("Distance: {p.distanceTo(Point.new(0.0, 0.0))}")
let nums = [1, 2, 3, 4, 5]
let names = ["Alice", "Bob", "Charlie"]
var arr = Array<Int>()
arr.push(1)
arr.push(2)
let first = arr.get(0)
let len = arr.length()
let zeros = Array<Int>.withLength(100)
var map = HashMap<String, Int>()
map.insert("alice", 30)
map.insert("bob", 25)
let age = map.get("alice")
See the Collections API for Vec, BTreeMap, LinkedList, and more.
0..10 // exclusive: 0, 1, 2, ..., 9
0..=10 // inclusive: 0, 1, 2, ..., 10
+, -, *, /, %
==, !=, <, <=, >, >=
and, or, not (also &&, ||, !)
&, |, ^, ~, <<, >>
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
Use as for type conversions:
let x: Int = 42
let f = x as Float
let s = x as String
import io
import collections.HashMap
pub makes declarations visible outside the module:
pub fun publicFunction() {
// accessible from other modules
}
fun privateFunction() {
// only accessible within this module
}
class Vec2 {
var x: Float
var y: Float
operator fun +(other: Vec2) r: Vec2 {
return Vec2.new(this.x + other.x, this.y + other.y)
}
operator fun *(scalar: Float) r: Vec2 {
return Vec2.new(this.x * scalar, this.y * scalar)
}
}
For low-level operations that bypass safety checks:
unsafe {
let ptr = transmute(address)
// raw pointer operations
}
Execute cleanup code when leaving a scope:
fun processFile(path: String) {
let file = File.open(path)
defer { file.close() }
// file is automatically closed when scope exits
let content = file.readContent()
}
Only executes if the scope exits via error:
fun allocateResource() r: Result<Resource, String> {
let res = acquire()
errdefer { release(res) }
let configured = configure(res)? // if this fails, res is released
return Ok(configured)
}
type Callback = Fun
type StringList = Array<String>
distinct Meters = Float
distinct Seconds = Float
// Meters and Seconds are incompatible even though both are Float
extension fun String.isBlank() r: Bool {
return trim(this) == ""
}
