Finite lists
When to use this. You want one column to hold an ordered group of values. How. Write a list literal with square brackets and commas:list<T> type, where T is any scalar type
(such as u32). List types nest, so list<list<u32>> is a column whose values are lists
of lists:
Take a list apart with a head/tail pattern
To split a list into its first element and the rest, use the cons pattern[H | T]
(a head-and-tail pattern). H binds to the first element (the head) and T binds to
everything after it (the tail):
| is a fixed prefix of elements; everything after it is the
remaining list. You can bind several leading elements at once, as in [A, B | Rest],
where A and B are the first two elements and Rest is the remainder.
A minimal program. Store one list, then read off its head:
first(10) — because 10 is
the head of the stored list.
Lists in XLOG are finite and interned. Interning means each distinct list is stored
once and given a dense integer ID at compile time.Because a
list<T> column is really an integer ID under the hood, it joins and compares
as fast as any integer column.The tradeoff: there are no unbounded or cyclic lists. A list you can write down is a list
the compiler can intern — and nothing else is representable.Meta-predicates
A meta-predicate inspects or manipulates terms and goals rather than plain data. Only one meta-predicate,=.. (read “univ”), is built into XLOG’s grammar. It relates a
compound term to a list of its functor and arguments — the same role it plays in Prolog.
(A term’s functor is the name at its head; its arguments are the values it holds.)
Every other meta-predicate is an ordinary atom recognized by its predicate name during
compilation. It is not a special piece of syntax — the compiler spots the name and expands
it.
findall/3 — collect answers into a list
When to use this. You want every value that satisfies a goal gathered into a single list. How.findall/3 collects every value of a template into a list:
Y for which edge(1, Y) holds and binds Xs to the resulting list.
maplist and functor/3
maplist applies a predicate across the elements of a list.
functor/3 relates a compound term to its functor name (the name at its head) and its
arity (how many arguments it takes).
Both are recognized by name and rewritten during compilation, in a step called
meta-normalization.
ground/1, var/1, nonvar/1 — decided at compile time
ground/1, var/1, and nonvar/1 look like runtime tests, but XLOG resolves them at
compile time, not while your program runs.
At the point where each call appears, the compiler already knows whether the term is bound
or ground. So the call resolves one of two ways: it succeeds and vanishes, or it becomes a
fail atom that prunes the rule.
They never execute as runtime checks. They are a compile-time decision about the shape of
your program, not a query against your data.
No runtime database
XLOG runs your rules repeatedly until no new facts can be derived — a fixpoint — and then stops. It has no mutable runtime database, so there is no way to add or remove facts while a program runs. The Prolog predicates that mutate the database are therefore rejected:Modules
Split a program across files, import selectively, and control visibility with
private.