Skip to content

Internal Prototype Hooks

Internal prototype hooks are special prototype members that the Nubo runtime looks for when it needs to perform language-level behavior.

Most user code should use normal syntax:

list[0]
dict["name"]
string(value)
clone(value)
valueof(value)
for item in value {
println(item)
}

Instead of calling internal hooks directly.

However, structs can define these hooks through impl, which lets custom types participate in built-in language behavior.

HookPurpose
__get__Handles indexed access like value[key].
__set__Handles indexed assignment like value[key] = other.
__iterate__Makes a value iterable in for loops.
__value__Returns an underlying primitive value for operations and valueof().
__string__Returns a string representation of a value.
__clone__Controls custom clone behavior.
__args__Function argument metadata.
__returns__Function return metadata.

Many built-in values already use internal hooks.

Lists use __get__ and __set__ for index access:

let items = ["a", "b"]
println(items[0])
items[1] = "x"
println(items)

Dictionaries use __get__ and __set__ for key access:

let user = {
"name": "Nubo"
}
println(user["name"])
user["name"] = "Cloud"
println(user["name"])

HTML elements use __get__ and __set__ for attributes:

let button = <button>Save</button>
button["id"] = "save-button"
println(button["id"])

Strings use __get__ for character access:

let text = "hello"
println(text[1])

When a struct defines hook methods inside impl, those methods become part of the struct instance prototype.

That means user-defined structs can behave like built-in values.

struct Box {
value: any
}
impl Box {
fn __string__(self: Box) string {
return "Box(" + string(self.value) + ")"
}
}
let box = Box()
box.value = 123
println(string(box))

In this example, Box defines __string__, so string conversion can use that hook.

__get__ powers indexed access.

value[key]

Built-in examples:

let items = ["a", "b"]
println(items[0])
let user = {
"name": "Nubo"
}
println(user["name"])

A custom struct can define __get__ to support index-like reads.

struct Store {
data: dict[string, any]
}
impl Store {
fn __get__(self: Store, key: string) any {
return self.data[key]
}
}
let store = Store()
store.data = {
"name": "Nubo"
}
println(store["name"])

Use this when your type behaves like a dictionary, list, element, or other container.

__set__ powers indexed assignment.

value[key] = other

Built-in examples:

let items = ["a", "b"]
items[0] = "x"
let user = {
"name": "Nubo"
}
user["name"] = "Cloud"

A custom struct can define __set__ to support index-like writes.

struct Store {
data: dict[string, any]
}
impl Store {
fn __set__(self: Store, key: string, value: any) void {
self.data[key] = value
}
fn __get__(self: Store, key: string) any {
return self.data[key]
}
}
let store = Store()
store.data = {}
store["name"] = "Nubo"
println(store["name"])

__value__ returns the underlying value of an object.

It is used when Nubo needs a primitive value from a struct-like object.

This is useful when a struct should behave like a number, string, or other base value during operations.

For example, the standard time.Time value can expose an integer-like value. That means an expression like this can work instead of failing immediately:

let future = time.now() + 10

The reason is that the time value can provide an underlying integer through __value__.

The built-in valueof() function is the readable way to get the value returned by __value__.

let raw = valueof(value)

Use valueof() in normal code instead of calling __value__ directly.

import time from "@std/time"
let now = time.now()
let raw = valueof(now)
println(raw)

A custom struct can define __value__.

struct Counter {
value: int
}
impl Counter {
fn __value__(self: Counter) any {
return self.value
}
}
let counter = Counter()
counter.value = 10
println(valueof(counter))

This makes the intent clearer than calling the hook manually.

// Prefer:
println(valueof(counter))
// Avoid in normal code:
println(counter.__value__())

__iterate__ makes a value iterable.

When Nubo sees a for loop, it can use __iterate__ to get an iterator from the value.

for item in value {
println(item)
}

If value has a __iterate__ hook, Nubo can call it to produce an iterator.

The iterator protocol is based on the @std/iter types:

TypePurpose
IteratorHolds a function that returns the next progress value.
ProgressRepresents one iteration step.
EndA special progress value meaning iteration is finished.

A progress value usually contains:

FieldDescription
keyIteration key or index.
valueIteration value.
endWhether the iterator is done.

Nubo includes a built-in range struct.

It has these fields:

FieldTypeDescription
startintStart value.
stopintStop value.
stepintStep amount.

range implements __iterate__, so it works in for loops.

for i in range(5) {
println(i)
}

This is equivalent to starting at 0 and stopping before 5.

for i in range(0, 5) {
println(i)
}

Use a custom step:

for i in range(0, 10, 2) {
println(i)
}

Use a negative step:

for i in range(5, 0, -1) {
println(i)
}

A step of 0 is invalid.

// Runtime error:
for i in range(0, 10, 0) {
println(i)
}

The range iterator stops when:

StepStop condition
Positive stepcurrent >= stop
Negative stepcurrent <= stop

You can use __iterate__ on custom structs to make them work with for.

A custom iterable should return an Iterator.

import iter from "@std/iter"
struct CountTo {
stop: int
}
impl CountTo {
fn __iterate__(self: CountTo) iter.Iterator {
let current = 0
return iter.Iterator(fn() iter.Progress {
if current >= self.stop {
return iter.End
}
let value = current
current = current + 1
return iter.Progress(value, value)
})
}
}
let counter = CountTo()
counter.stop = 3
for i in counter {
println(i)
}

Expected output:

0
1
2

This pattern is useful for custom collections, streams, cursors, query results, ranges, and generated sequences.

__string__ returns a string representation of a value.

Nubo can use this hook when converting a value to a string.

struct User {
name: string
}
impl User {
fn __string__(self: User) string {
return "User(" + self.name + ")"
}
}
let user = User()
user.name = "Martin"
println(string(user))

Expected output:

User(Martin)

Use __string__ when your struct should have a clear readable representation.

Good examples:

struct Point {
x: int
y: int
}
impl Point {
fn __string__(self: Point) string {
return "Point(" + string(self.x) + ", " + string(self.y) + ")"
}
}

__clone__ controls how a value is cloned.

When a struct has custom ownership or nested data, __clone__ can return a controlled copy.

struct User {
name: string
roles: []string
}
impl User {
fn __clone__(self: User) User {
let copy = User()
copy.name = self.name
copy.roles = clone(self.roles)
return copy
}
}

Use the built-in clone() function in normal code.

let copied = clone(user)

Prefer:

let copied = clone(user)

Avoid calling the hook directly:

// Avoid in normal code:
let copied = user.__clone__()

Functions expose metadata through prototype values.

fn add(a: int, b: int) int {
return a + b
}
println(add.__args__)
println(add.__returns__)

__args__ contains function argument metadata.

Each argument can include:

KeyDescription
nameArgument name.
typeArgument type.
defaultDefault value, or nil.

Example:

fn greet(name: string, excited: bool = false) string {
if excited {
return "Hello, " + name + "!"
}
return "Hello, " + name
}
println(greet.__args__)

__returns__ contains return type metadata.

fn greet(name: string) string {
return "Hello, " + name
}
println(greet.__returns__)

For union returns, this can be represented as multiple possible type names.

Use normal language syntax when possible.

list[0]
dict["name"]
element["id"]
for item in value {
println(item)
}
string(value)
clone(value)
valueof(value)

Use internal hooks when you are implementing behavior for a custom struct.

impl Store {
fn __get__(self: Store, key: string) any {
return self.data[key]
}
fn __set__(self: Store, key: string, value: any) void {
self.data[key] = value
}
}

Avoid calling hooks directly from regular app code.

// Prefer:
println(valueof(counter))
// Avoid:
println(counter.__value__())
HookUser-facing behavior
__get__Enables value[key].
__set__Enables value[key] = other.
__iterate__Enables for item in value.
__value__Enables readable conversion through valueof(value) and can help operations use an underlying primitive.
__string__Enables readable string conversion through string(value).
__clone__Enables custom copying through clone(value).
__args__Exposes function argument metadata.
__returns__Exposes function return metadata.