Skip to content

Variables and Types

Nubo provides a clean and expressive type system with type inference, explicit annotations, structs, interfaces, and union types.

Use the let keyword for mutable values:

let name = "Martin"
let age = 19
let isAdmin = true

Variables declared with let can be reassigned:

let sum = 0
sum = sum + 10

Use const for immutable values:

const VERSION = "1.0.0"

Constants are useful for values that should not change after initialization.

Nubo includes common built-in types:

  • byte — single byte (bytes can be used to convert values to a []byte)
  • int — whole numbers
  • float — decimal numbers
  • booltrue or false
  • string — text values
  • char — a single character
  • []T — a list of values of type T
  • dict[K, V] — key-value storage
  • fn(...) -> ... — function types (-> only required for the type declaration of the function, not the actual use)
  • struct — custom data types
  • iface — structural interfaces
  • nil — an empty or missing value
  • any — any type

Types are inferred when not specified:

let title = "Nubo" // string
let count = 5 // int
let enabled = true // bool

Types can be explicitly defined using ::

let x: int = 5
const name: string = "John"
let names: []string = ["Ana", "Bob"]

A value can accept more than one type using |:

let s: string|nil = "Hello"

Union types are useful when a value may be present or missing.

if s == nil {
println("No value")
}

You can also create named union types:

type NumberOrText: int|string

Use type() to inspect the runtime type of a value:

let s: string|nil = "Hello"
println(s, type(s))

Create custom data types with struct:

struct User {
name: string
roles: []string
data: dict[string, int]
}

Structs can be constructed by calling the struct name:

const user = User("John")

Use impl to define methods for a struct:

struct User {
name: string
}
impl User {
fn init(self: User, name: string) void {
self.name = name
}
fn sayHello(self: User) void {
println(`Hi! I am ${self.name}!`)
}
}
const john = User("John")
john.sayHello()

Functions are first-class values:

let add = fn(a: int, b: int) int {
return a + b
}

Functions can also be declared by name:

fn add(a: int, b: int) int {
return a + b
}

Use void when a function does not return a value:

fn log(message: string) void {
println(message)
}