Facts route to storage purely by syntax — never by current database content or write order.
node(Id).
node(Id, [Labels], { props... }).
label(Id, Label).
property(Id, Key, Value).
edge(Source, Type, Target).
edge(Source, Type, Target, { props... }).
edge/4 is the only way to write a property-bearing edge.
person(alice). % label shortcut -> label(alice, person)
knows(alice, bob). % edge-type shortcut -> edge(alice, knows, bob)
prop_name(alice, Name). % property shortcut -> property(alice, name, Name)
Writing Label(Id) to an existing node merges the label and preserves existing properties.
? retract(person(alice)).
? retract(edge(alice, knows, bob)).
? retract(prop_title(alice, _)).
? retract(impart(zlf, _, _)).
retract/1 removes the first match; retractall/1 removes every match. Wildcards (_) and consistent named variables are supported.
Unreserved ground facts of arity three or greater are durable logical facts in the general FactStore:
| Form | Owner | Meaning |
|---|---|---|
node(...), label(...), property(...), edge(...) |
graph storage | canonical contracts |
unreserved P/1 |
graph storage | label shortcut |
unreserved P/2 |
graph storage | edge-type shortcut |
unreserved ground P/3+ |
FactStore | first-class logical fact |
impart(zlf, katurupi, tongtong).
? impart(zlf, From, To).
? retract(impart(zlf, katurupi, tongtong)).
? retractall(impart(zlf, _, _)).
Semantics:
a(b, b, d). and a(b, d, b). are distinct, as are a("x", y, z). vs a(x, y, z). and a(1, y, z). vs a(1.0, y, z).asserta/1 and assertz/1 store logical facts by identity with no clause-order guarantee; iteration is canonical key order.(name, arity) collides with a builtin/index/graph predicate (bm25/3, append/3, functor/3, call/3..8, edge_id/4) or a canonical graph name at arity >= 3 (node/4) is rejected with a clear error.edge/4. knows(alice, bob, { since: 2024 }). is a logical fact, never an edge.