Data Library (Data)
Every field and function is backed by a Data handle — this library is how you work with that handle directly, rather than through the field or function it's attached to. Advanced, low-level territory; most code never needs this.
Locating Data
Data.field(path: str) -> data
A data pointer to a field, by path from the current object.
myfield: 42
#[main]
fn main() {
const ptr = Data.field('self.myfield');
pln(ptr.exists());
}Data.id(ptr: data) -> str
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const id = func.data().id();
pln(id.len() > 0);
}Data.from_id(id: str) -> data
The other direction — reconstruct a pointer from an ID string.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const id = func.data().id();
pln(Data.from_id(id) == func.data());
}Data.libname(ptr: data) -> str
Which library this data is linked to, if any.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
pln(func.data().libname());
}Data.objs(ptr: data) -> list
Every object this data is attached to.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
pln(func.data().objs().front() == self);
}Attaching, Moving & Dropping
Data.attach(ptr: data, obj: obj) -> bool
Makes this data reachable from an additional object, under the same name.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const other = new {};
func.data().attach(other);
pln(other.hi());
}Data.move(ptr: data, from: obj, to: obj) -> bool
A drop and an attach in one step — removes the data from one object and places it on another.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const other = new {};
func.data().move(self, other);
pln(other.hi(), self.hi);
}Data.drop(ptr: data) -> bool
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
pln(func.data().drop());
}Data.drop_from(ptr: data, obj: obj) -> bool
Drops from one specific object — if that was the only object referencing it, the data leaves the document entirely.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
pln(func.data().drop_from(self));
}Serialization
Data.blob(ptr: data) -> blob
Serializes the data (name, attributes, value — everything) into bytes.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const bin = func.data().blob();
pln(bin.len() > 0);
}Data.load_blob(bytes: blob, context: obj | str = self) -> data
The other direction — deserializes into a specific object, effectively copying the data onto it.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const bin = func.data().blob();
const other = new {};
Data.load_blob(bin, other);
pln(other.hi());
}Validity
Data.exists(ptr: data) -> bool
False once the data has been dropped — a pointer held onto after that point doesn't resurrect it.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func: fn = self.hi;
const ptr = func.data();
drop(func);
pln(ptr.exists());
}Data.invalidate(data: data, symbol: str = 'value') -> bool
Marks data as invalid under a symbol — a lightweight dirty-flag mechanism, throws if the data doesn't exist.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func = self.hi;
const ptr = func.data();
pln(ptr.invalidate('something_happened'));
}Data.validate(data: data, symbol?: str) -> bool
Clears an invalidation — returns true only if it was actually invalid under that symbol (or any symbol, if none given) beforehand.
fn hi() -> str { 'hi' }
#[main]
fn main() {
const func = self.hi;
const ptr = func.data();
ptr.invalidate('something_happened');
pln(ptr.validate('something_happened'));
pln(ptr.validate('something_happened'));
}