Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

zuri.reflect

import zuri

zuri exposes this as zuri.reflect, so import zuri is enough and the names are called as zuri.reflect.*. import zuri.reflect reaches the same definitions directly.

Runtime introspection: metadata about a live function, class, or module, and property/method access on an instance or module by name, without needing to already know that name at compile time. It also runs the garbage collector on demand.

This is deliberately a RUNTIME-only view. It does not know a function/class’s declaration line or its doc block; those live in source, not in the running object, and are a zuri.parse()/zuri AST concern instead (walk the parsed source and read a Function/Class node’s own line/col, and any DocBlock node sitting right before it).

import zuri

def add(a, b) {
  return a + b
}

echo zuri.reflect.function_info(add).arity
# 2

Functions

kind()

zuri.reflect.kind(value) -> string

This value’s runtime type tag: 'nil', 'bool', 'number', 'string', 'bytes', 'bigint', 'list', 'dict', 'function', 'class', 'instance', 'module', 'range', 'file', or a pointer’s own registered resource tag (see pointer_type). A closure, a native function, and a bound method are all reported as 'function', since from Zuri’s own point of view they’re interchangeably callable.

Parameters

  • value (any)

Returns string

pointer_type()

zuri.reflect.pointer_type(value) -> ?string

The registered resource tag a pointer value was allocated with (e.g. a native socket handle’s own internal type name), or nil if value isn’t a pointer at all. Pointers wrap an opaque native resource that Zuri code can’t otherwise inspect; this names what kind of resource one is without exposing its contents.

Parameters

  • value (any)

Returns ?string

function_info()

zuri.reflect.function_info(f) -> dict

Metadata for a function-like value: { name, arity, variadic, is_method, owning_class_name, source_path }. owning_class_name is the class it was declared a method of, or nil for an ordinary function/closure. source_path is nil for a native (built-in) function, which has no Zuri source file behind it.

Parameters

  • f (callable) — A closure, a native function, or a bound method

Returns dict

Raises Error if f isn’t callable as a function (a class, though itself callable to construct an instance, is a class_info subject instead)

class_info()

zuri.reflect.class_info(c) -> dict

Metadata for a class: { name, superclass_name, methods, fields, statics }. superclass_name is nil for a class with no superclass. methods is a dict from method name to that method’s own function_info-shaped entry, own and inherited pre-merged (an override shadows the inherited entry of the same name, matching how method dispatch itself works). fields and statics are plain lists of names, ordered by declaration; fields includes inherited fields, statics is own-only (statics are never inherited in this runtime).

Parameters

  • c (class)

Returns dict

Raises Error if c isn’t a class

module_info()

zuri.reflect.module_info(m) -> dict

Metadata for a module: { name, path, loaded, members }. members is a dict from every top-level name the module declares to that binding’s own kind (see kind above), e.g. { add: 'function', VERSION: 'string' }. Accepts either a raw module value or a promoted import PATH binding; both describe the same underlying module.

Parameters

  • m (module)

Returns dict

Raises Error if m isn’t a module

info()

zuri.reflect.info(value) -> dict

Dispatches to function_info/class_info/module_info based on kind(value).

Parameters

  • value (any)

Returns dict

Raises Error if value has no reflectable shape (a number, a list, an instance, …); reflect describes callables, classes, and modules only

has_prop()

zuri.reflect.has_prop(object, name) -> bool

Does object (an instance or a module) have a property/member named name?

Parameters

  • object (instance|module)
  • name (string)

Returns bool

get_prop()

zuri.reflect.get_prop(object, name) -> any

The current value of object’s (an instance or a module) property/member named name, or nil if it has none by that name.

Parameters

  • object (instance|module)
  • name (string)

Returns any

Raises TypeError if object is neither an instance nor a module

get_props()

zuri.reflect.get_props(object) -> list[string]

Every property/member name object (an instance or a module) has, as a list of strings, or an empty list if it has none. Instance fields are ordered by declaration; module members have no such inherent order.

Parameters

  • object (instance|module)

Returns list[string]

Raises TypeError if object is neither an instance nor a module

set_prop()

zuri.reflect.set_prop(object, name, value)

Overwrites object’s existing property name with value.

Parameters

  • object (instance)
  • name (string)

Returns — bool: true if the property was updated, false if name isn’t a field object’s class declares (nothing is changed in that case; this never creates a new field)

Raises TypeError if object isn’t an instance

Note: instances in this runtime have a fixed set of fields, sized once when their class is declared. Unlike a dict, a property can never be added to or removed from an instance at runtime. This only ever updates a field the instance’s class already declares; it can’t create a new one.

del_prop()

zuri.reflect.del_prop(object, name)

Resets object’s existing property name back to nil.

Parameters

  • object (instance)
  • name (string)

Returns — bool: true if the property was reset, false if name isn’t a field object’s class declares

Raises TypeError if object isn’t an instance

Note: as with set_prop, this can’t remove the field itself, only clear its value; see set_prop’s own note.

has_method()

zuri.reflect.has_method(object, name) -> bool

Does the class behind object (an instance, or a class used directly) declare or inherit a method named name?

Parameters

  • object (instance|class)
  • name (string)

Returns bool

has_decorator()

zuri.reflect.has_decorator(object, name) -> bool

Does the class behind object implement the decorator named name? A decorator is just a method whose own name starts with @ (@to_string, @new, @value, …); name here excludes that leading @.

Parameters

  • object (instance|class)
  • name (string) — The decorator’s name, without the leading @

Returns bool

get_method()

zuri.reflect.get_method(object, name) -> ?function

The raw (unbound) closure for method name on the class behind object, or nil if it declares no such method. Calling the result directly does NOT supply a receiver; see bind_method for a version that does.

Parameters

  • object (instance|class)
  • name (string)

Returns ?function

bind_method()

zuri.reflect.bind_method(object, name) -> ?function

Method name on object’s class, bound to object itself as the receiver; the result can be called directly with no receiver argument, unlike get_method’s raw closure.

Parameters

  • object (instance)
  • name (string)

Returns ?function

get_decorator()

zuri.reflect.get_decorator(object, name) -> function

The decorator function named name (excluding the leading @) on the class behind object, bound to object as its receiver and ready to call directly.

Parameters

  • object (instance)
  • name (string) — The decorator’s name, without the leading @

Returns function

Raises NotImplementedError if the class behind object implements no such decorator

gc()

zuri.reflect.gc() -> nil

Runs a full garbage collection now, instead of waiting for the heap to cross its threshold.

Every object nothing reaches is freed before this returns, and anything that releases a resource when collected releases it: an owned ffi pointer’s destructor runs, for one. The memory freed goes back to the system before this returns too.

A program never needs this to stay correct; the collector runs on its own as the program allocates. It is for the moments the timing matters: releasing native resources at a known point, or a test that checks what collection does. A full collection visits every live object, so calling it in a loop is slow.

import zuri

var scratch = [1, 2, 3]
scratch = nil
zuri.reflect.gc()

Returns nil


2026, Richard Ore and Zuri contributors