Skip to main content

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.

Covered in The Document Graph.

Obj.name(obj: obj) -> str

obj-name.stof
#[main]
fn main() {
  const obj = new {};
  pln(obj.name().len() > 0);
}
Output

Obj.path(obj: obj) -> str

obj-path.stof
#[main]
fn main() {
  pln(self.path());
}
Output

Obj.id(obj: obj) -> str

obj-id.stof
#[main]
fn main() {
  const obj = new {};
  pln(obj.id().len() > 0);
}
Output

Obj.parent(obj: obj) -> obj

obj-parent.stof
#[main]
fn main() {
  const obj = new {};
  pln(obj.parent() == self);
}
Output

Obj.root(obj: obj) -> obj

obj-root.stof
#[main]
fn main() {
  const obj = new {};
  pln(obj.root() == self);
}
Output

Obj.is_root(obj: obj) -> bool

obj-is-root.stof
#[main]
fn main() {
  pln(self.is_root());
}
Output

Obj.children(obj: obj) -> list

obj-children.stof
#[main]
fn main() {
  const obj = new {};
  pln(self.children());
}
Output

Obj.dist(obj: obj, other: obj) -> int

Number of edges separating two objects.

obj-dist.stof
#[main]
fn main() {
  const obj = new {};
  pln(obj.dist(self));
}
Output

Obj.is_parent(obj: obj, other: obj) -> bool

obj-is-parent.stof
#[main]
fn main() {
  const obj = new {};
  pln(self.is_parent(obj));
}
Output

Obj.exists(obj: obj) -> bool

False once dropped — holding a reference afterward doesn't bring it back.

obj-exists.stof
#[main]
fn main() {
  const obj = new {};
  pln(obj.exists());
}
Output

Fields & Data

Obj.len(obj: obj) -> int

Number of fields.

obj-len.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.len());
}
Output

Obj.any(obj: obj) -> bool

Has any data attached at all.

obj-any.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.any());
}
Output

Obj.empty(obj: obj) -> bool

obj-empty.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.empty());
}
Output

Obj.contains(obj: obj, name: str) -> bool

obj-contains.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.contains("y"));
}
Output

Obj.get(obj: obj, name: str) -> unknown

A field's value, a function, or a data pointer — by name.

obj-get.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.get("x"));
}
Output

Obj.at(obj: obj, index: int) -> (str, unknown)

The (name, value) field at a given index.

obj-at.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj[1]);
}
Output

Obj.fields(obj: obj) -> list

Every (name, value) field, as a list.

obj-fields.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.fields());
}
Output

Obj.funcs(obj: obj, attributes: str | list | set = null) -> list

Every function on this object, optionally filtered by attribute.

obj-funcs.stof
#[myfunc]
fn func() {}

#[main]
fn main() {
  pln(self.funcs("myfunc").len());
}
Output

Obj.insert(obj: obj, path: str, value: unknown) -> void

Creates or assigns, using obj as the starting context — same as a normal field assignment.

obj-insert.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  obj.insert("z", 9);
  pln(obj.z);
}
Output

Obj.move_field(obj: obj, source: str, dest: str) -> bool

Rename or move a field — like mv for a field path.

obj-move-field.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  obj.move_field("x", "dude");
  pln(obj.dude, obj.contains("x"));
}
Output

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.

obj-remove.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  pln(obj.remove("x"), obj.contains("x"));
}
Output

Obj.attributes(obj: obj, path: str = null) -> map

This object's own attributes, or a specific field/func/object's if path is given.

obj-attributes.stof
#[a]
value: 42

#[main]
fn main() {
  pln(self.attributes("value"));
}
Output

Obj.to_map(obj: obj) -> map

obj-to-map.stof
#[main]
fn main() {
  const obj = new { x: 3km, y: 5.5m };
  const map = obj.to_map();
  pln(map.get("x"));
}
Output

Obj.from_map(map: map) -> obj

obj-from-map.stof
#[main]
fn main() {
  const map = { "x": 0, "y": 0 };
  const obj = Obj.from_map(map);
  pln(obj.x);
}
Output

Obj.from_id(id: str) -> obj

Objects are references, same as data — reconstruct one from its ID.

obj-from-id.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  const ptr = Obj.from_id(obj.id());
  pln(ptr == obj);
}
Output

Prototypes

Covered in depth in Prototypes & Schemas.

Obj.create_type(obj: obj, typename: str) -> void

Programmatic equivalent of #[type].

obj-create-type.stof
#[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);
}
Output

Obj.set_prototype(obj: obj, proto: obj | str) -> void

obj-set-prototype.stof
#[main]
fn main() {
  const proto = new {};
  const obj = new {};
  obj.set_prototype(proto);
  pln(obj.prototype() == proto);
}
Output

Obj.remove_prototype(obj: obj) -> void

obj-remove-prototype.stof
#[type]
MyType: {}

#[main]
fn main() {
  const obj = new MyType {};
  obj.remove_prototype();
  pln(typename obj);
}
Output

Obj.prototype(obj: obj) -> obj

null if there isn't one.

obj-prototype.stof
#[main]
fn main() {
  pln(self.prototype());
}
Output

Obj.instance_of(obj: obj, proto: str | obj) -> bool

obj-instance-of.stof
#[type]
MyType: {}

#[main]
fn main() {
  const obj = new MyType {};
  pln(obj.instance_of("MyType"));
}
Output

Obj.upcast(obj: obj) -> bool

Sets this object's prototype to its current prototype's own prototype — one step up an inheritance chain.

obj-upcast.stof
#[type]
SuperType: {}

#[type]
#[extends('SuperType')]
SubType: {}

#[main]
fn main() {
  const obj = new SubType {};
  obj.upcast();
  pln(typename obj);
}
Output

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).

obj-move.stof
#[main]
fn main() {
  const obj = new { x: 0, y: 0 };
  const other = new {};
  obj.move(other);
  pln(obj.parent() == other);
}
Output

Obj.run(obj: obj) -> void

Covered in depth in Object Run.

obj-run.stof
Workflow: {
  #[run]
  fn step() { pln('ran'); }
}

#[main]
fn main() {
  self.Workflow.run();
}
Output

Obj.schemafy(schema: obj, target: obj, remove_invalid: bool = false, remove_undefined: bool = false) -> bool

Covered in depth in Prototypes & Schemas.

obj-schemafy.stof
schema: {
  #[schema((target_value: str): bool => target_value.len() > 2)]
  first: 'John'
}

target: {
  first: 'aj'
}

#[main]
fn main() {
  pln(self.schema.schemafy(self.target));
}
Output

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.

obj-diff.stof
#[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);
}
Output

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.

obj-dbg-graph.stof
#[main]
fn main() {
  Obj.dbg_graph();
}
Output