Object Library (Obj)
Linked to the obj type. A lot of this library is already covered in depth elsewhere — Document Graph, Prototypes & Schemas, and Object Run — so those entries stay brief here and link back rather than re-explain; anything new to this page gets the full treatment.
Navigation
Covered in The Document Graph.
Obj.name(obj: obj) -> str
#[main]
fn main() {
const obj = new {};
pln(obj.name().len() > 0);
}Obj.path(obj: obj) -> str
#[main]
fn main() {
pln(self.path());
}Obj.id(obj: obj) -> str
#[main]
fn main() {
const obj = new {};
pln(obj.id().len() > 0);
}Obj.parent(obj: obj) -> obj
#[main]
fn main() {
const obj = new {};
pln(obj.parent() == self);
}Obj.root(obj: obj) -> obj
#[main]
fn main() {
const obj = new {};
pln(obj.root() == self);
}Obj.is_root(obj: obj) -> bool
#[main]
fn main() {
pln(self.is_root());
}Obj.children(obj: obj) -> list
#[main]
fn main() {
const obj = new {};
pln(self.children());
}Obj.dist(obj: obj, other: obj) -> int
Number of edges separating two objects.
#[main]
fn main() {
const obj = new {};
pln(obj.dist(self));
}Obj.is_parent(obj: obj, other: obj) -> bool
#[main]
fn main() {
const obj = new {};
pln(self.is_parent(obj));
}Obj.exists(obj: obj) -> bool
False once dropped — holding a reference afterward doesn't bring it back.
#[main]
fn main() {
const obj = new {};
pln(obj.exists());
}Fields & Data
Obj.len(obj: obj) -> int
Number of fields.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.len());
}Obj.any(obj: obj) -> bool
Has any data attached at all.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.any());
}Obj.empty(obj: obj) -> bool
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.empty());
}Obj.contains(obj: obj, name: str) -> bool
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.contains("y"));
}Obj.get(obj: obj, name: str) -> unknown
A field's value, a function, or a data pointer — by name.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.get("x"));
}Obj.at(obj: obj, index: int) -> (str, unknown)
The (name, value) field at a given index.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj[1]);
}Obj.fields(obj: obj) -> list
Every (name, value) field, as a list.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.fields());
}Obj.funcs(obj: obj, attributes: str | list | set = null) -> list
Every function on this object, optionally filtered by attribute.
#[myfunc]
fn func() {}
#[main]
fn main() {
pln(self.funcs("myfunc").len());
}Obj.insert(obj: obj, path: str, value: unknown) -> void
Creates or assigns, using obj as the starting context — same as a normal field assignment.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
obj.insert("z", 9);
pln(obj.z);
}Obj.move_field(obj: obj, source: str, dest: str) -> bool
Rename or move a field — like mv for a field path.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
obj.move_field("x", "dude");
pln(obj.dude, obj.contains("x"));
}Obj.remove(obj: obj, path: str, shallow: bool = false) -> bool
Same operation as Std.drop, from obj as context — see Document Memory Management for the full shallow behavior.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
pln(obj.remove("x"), obj.contains("x"));
}Obj.attributes(obj: obj, path: str = null) -> map
This object's own attributes, or a specific field/func/object's if path is given.
#[a]
value: 42
#[main]
fn main() {
pln(self.attributes("value"));
}Obj.to_map(obj: obj) -> map
#[main]
fn main() {
const obj = new { x: 3km, y: 5.5m };
const map = obj.to_map();
pln(map.get("x"));
}Obj.from_map(map: map) -> obj
#[main]
fn main() {
const map = { "x": 0, "y": 0 };
const obj = Obj.from_map(map);
pln(obj.x);
}Obj.from_id(id: str) -> obj
Objects are references, same as data — reconstruct one from its ID.
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
const ptr = Obj.from_id(obj.id());
pln(ptr == obj);
}Prototypes
Covered in depth in Prototypes & Schemas.
Obj.create_type(obj: obj, typename: str) -> void
Programmatic equivalent of #[type].
#[main]
fn main() {
const obj = new { float x: 0, float y: 0 };
obj.create_type("MyType");
const ins = new MyType {};
pln(typename ins, ins.prototype() == obj);
}Obj.set_prototype(obj: obj, proto: obj | str) -> void
#[main]
fn main() {
const proto = new {};
const obj = new {};
obj.set_prototype(proto);
pln(obj.prototype() == proto);
}Obj.remove_prototype(obj: obj) -> void
#[type]
MyType: {}
#[main]
fn main() {
const obj = new MyType {};
obj.remove_prototype();
pln(typename obj);
}Obj.prototype(obj: obj) -> obj
null if there isn't one.
#[main]
fn main() {
pln(self.prototype());
}Obj.instance_of(obj: obj, proto: str | obj) -> bool
#[type]
MyType: {}
#[main]
fn main() {
const obj = new MyType {};
pln(obj.instance_of("MyType"));
}Obj.upcast(obj: obj) -> bool
Sets this object's prototype to its current prototype's own prototype — one step up an inheritance chain.
#[type]
SuperType: {}
#[type]
#[extends('SuperType')]
SubType: {}
#[main]
fn main() {
const obj = new SubType {};
obj.upcast();
pln(typename obj);
}Structural Operations
Obj.move(obj: obj, dest: obj) -> bool
Reparent — dest can't be a descendant of obj (no detaching a node from its own subtree).
#[main]
fn main() {
const obj = new { x: 0, y: 0 };
const other = new {};
obj.move(other);
pln(obj.parent() == other);
}Obj.run(obj: obj) -> void
Covered in depth in Object Run.
Workflow: {
#[run]
fn step() { pln('ran'); }
}
#[main]
fn main() {
self.Workflow.run();
}Obj.schemafy(schema: obj, target: obj, remove_invalid: bool = false, remove_undefined: bool = false) -> bool
Covered in depth in Prototypes & Schemas.
schema: {
#[schema((target_value: str): bool => target_value.len() > 2)]
first: 'John'
}
target: {
first: 'aj'
}
#[main]
fn main() {
pln(self.schema.schemafy(self.target));
}Obj.diff(schema: obj, target: obj, symmetric: bool = false) -> void
Removes every field from target that matches schema, recursively — leaving only what's actually different. symmetric also copies over anything unique to schema.
#[main]
fn main() {
const sch = new { x: 3km, y: 5.5m };
const other = new { x: 3km, y: 5.6m };
let difference = copy(other);
sch.diff(difference);
pln(difference.x, difference.y);
}Obj.dbg_graph() -> void
Dumps the entire graph — useful for debugging, expect dense output. For one specific node instead of the whole graph, Std.dbg(node) is the better tool.
#[main]
fn main() {
Obj.dbg_graph();
}