Skip to content

Reflection

@std/reflect wraps a Nubo value or struct definition in a mirror. A mirror inspects the original object; it is not an independent deep copy.

import reflect from "@std/reflect"
let text = "hello"
let mirror = reflect.Of(text)
println(mirror.kind())
println(mirror.type())
println(mirror.call("includes", ["ell"]))
ExportMeaning
Of(value)Return a mirror for a value or definition.
StructMirror struct type.
kind(value)Broad runtime kind as a string.
type(value)Nubo type description as a string.
typeOf(value), getType(value)Aliases for type(value).
Mirror methodResult
kind()Runtime kind.
type(), typeOf(), getType()Type description.
id()Runtime object ID.
inspect()Inspection string.
string()Object string representation.
value()Reflected object.
isStruct()Whether it is a struct definition or instance.
isFunction()Whether it is a function.
fields(includePrivate: bool = false)Field descriptors.
methods(includePrivate: bool = false)Method descriptors.
members(includePrivate: bool = false)Fields and methods together.
has(name, includePrivate: bool = false)Whether a member is visible.
get(name, includePrivate: bool = false)Member value, or nil if unavailable.
signature()Function signature descriptor, or nil for non-functions.
import reflect from "@std/reflect"
struct User {
name: string
private token: string
}
impl User {
fn greet(self: User, prefix: string = "Hello") string {
return prefix + ", " + self.name
}
}
let user = User(name: "Ada")
let mirror = reflect.Of(user)
println(mirror.fields())
println(mirror.methods())
println(mirror.has("name"))
println(mirror.get("name"))

Field descriptors include information such as name, type, privacy, and value. Method descriptors include method/signature information. Methods obtained from instances bind self.

import reflect from "@std/reflect"
struct Person {
name: string
}
impl Person {
fn init(self: Person, name: string = "Guest") void {
self.name = name
}
fn greet(self: Person, prefix: string = "Hello") string {
return prefix + ", " + self.name
}
}
let definition = reflect.Of(Person)
let person = definition.new(["Ada"])
let mirror = reflect.Of(person)
println(mirror.call("greet"))
println(mirror.call("greet", ["Welcome"]))
mirror.set("name", "Nubo")
println(person.name)
  • new(args = []) requires a struct definition and invokes its initializer, including an automatic initializer when present.
  • call(name, args = [], includePrivate = false) invokes a method on an instance or another value that has that method.
  • set(name, value, includePrivate = false) changes a declared field of a struct instance. It does not add arbitrary fields or methods.
  • Pass positional argument values in the args list. Omitted values can use the initializer or method’s defaults.
  • Void method calls produce nil through the reflection API. Invalid targets, argument mismatches, and failed calls raise Nubo errors.
import reflect from "@std/reflect"
fn greet(name: string = "World") string {
return "Hello, " + name
}
let mirror = reflect.Of(greet)
println(mirror.isFunction())
println(mirror.signature())
import reflect from "@std/reflect"
type Greeter: iface {
greet(prefix: string) string
}
type GreetingFunction: fn(string) -> string
struct Person {
name: string
}
impl Person {
fn greet(self: Person, prefix: string) string {
return prefix + ", " + self.name
}
}
let person = Person(name: "Ada")
let mirror = reflect.Of(person)
println(mirror.implements(Greeter))
println(mirror.implements(dict[string, any] {
name: string,
greet: GreetingFunction
}))

implements(contract) accepts a Nubo interface or a dictionary describing public member types. Private methods do not satisfy a public contract. Checking a definition does not run its user initializer.

Normal reflection hides private members. The APIs that accept includePrivate allow callers to opt into private inspection or access:

import reflect from "@std/reflect"
struct Secret {
private token: string
}
let secret = Secret()
let mirror = reflect.Of(secret)
println(mirror.has("token"))
mirror.set("token", "updated", true)
println(mirror.get("token", true))

Private fields are an ordinary-access boundary, not a sandbox against code explicitly using private reflection. Mirror operations do not implicitly inherit private access merely because they were called from inside another method.