π me.whatever(what)
Writing with me.a.b(value), reading with me("a.b").
Every property access on
meextends a path. Calling it with a value declares; calling the root with the path string reads.
Kernel: this.me 4.2.1 (npm) β
Source: createProxy in proxy.ts, handleCall in handleCall.ts, postulate in core-write.ts.
Write and read
import { ME } from "this.me";
const me = new ME() as any;
me.colony.ants.workers[1].carry(3); // write: colony.ants.workers.1.carry = 3
me("colony.ants.workers.1.carry"); // read β 3
me("colony.ants.workers[1].carry"); // read β 3 (same path)
me.a.bbuilds the path["a", "b"]; nothing is read or written until it is called (createProxy).me.a.b(value)declaresvalueata.b(postulate(path, value)), recomputes what depends on it, and returns a proxy on the same path, so calls chain.me("a.b")reads. At the root, a single string that is a dotted path, a single label, or starts with_,~or@is routed to the read (handleCall).workers[1]andworkers.1name the same segment.
A call with no argument is not a read: me.a.b() writes undefined at a.b (handleCall.ts). To read, always use me("a.b").
Chaining
me.colony.chambers.nursery("warm").depth(4); // nursery = "warm", then nursery.depth = 4
me("colony.chambers.nursery"); // β "warm"
me("colony.chambers.nursery.depth"); // β 4
A write returns a proxy on the path it wrote (an operator leaf returns its scope instead), so the next segment continues from there.
A path can also point to another path. Reads go through the pointer (more on pointers):
me.colony.ants.workers[1].home["->"]("colony.chambers.nursery");
me("colony.ants.workers.1.home"); // β { "__ptr": "colony.chambers.nursery" }
me("colony.ants.workers.1.home.depth"); // β 4, read through the pointer
Derived values
me.colony.pantry.seeds(40);
me.colony.pantry.honey(12);
me.colony["="]("food", "pantry.seeds + pantry.honey");
me("colony.food"); // β 52
me.colony.pantry.seeds(45); // more seeds arrive
me("colony.food"); // β 57, recomputed
["="] declares a formula on a path; reading it is the same me(path), and it follows its inputs.
colony.pantry.seeds + colony.pantry.honey β colony.food = 57, after seeds(45)Why a path has its value
me.explain("colony.food"); // value, formula, inputs and the last wave
me.explain(path) is a kernel member, not a path: it returns the value with the formula, the inputs it read and the wave that last recomputed it (see me.explain()).
Names that are not paths
The proxy first checks whether the property exists on the kernel instance (Proxy calls, source: proxy.ts): if it does, you get that member, not a path. Public examples: me.explain, me.inspect, me.execute, me.exportSnapshot, me.hydrate, me.setRecomputeMode, me.getRecomputeMode, me.prove, me.learn. Inherited object names (toString, constructor) are also members. me["!"] enters the runtime plane.
Any other name is a path.
Rust has no proxy: members are methods on Kernel and a path is always an argument, so a path can never be mistaken for a member. Write with kernel.postulate("a.b", v), read with kernel.read("a.b"), explain with kernel.explain("a.b"); strings become paths through IntoPath (Rust API, source: path.rs).
Root calls
| Call | What it does |
|---|---|
me("a.b") |
Reads the path. |
me() |
Returns the root proxy. |
me("ana", "luna") |
Two strings, the first a bare label: seeds the identity (who + secret). |
me(expression) |
Anything else: a root postulate. |
See also
Robots That Understand Context Β· Ant City (the colony as a live demo) Β· Primitives (the two verbs: declare and resolve) Β· me:// URI grammar Β· Syntax Β· Axioms (A-struct-0: one callable, chainable value)