Lists¶
Lists are the fundamental data structure in logic programming. Clausal uses Python's native list syntax — no cons cells, no special notation.
Strings work too
All list predicates accept strings as character lists. append("hel", "lo", X)
yields X = "hello", in_('e', "hello") succeeds, and reverse("hello", X)
yields X = "olleh". See Strings as Lists for the full
story.
Quick Example¶
palindrome(XS) <- (reverse(XS, XS))
Test("palindrome") <- palindrome([1, 2, 1])
Test("not palindrome") <- (not palindrome([1, 2, 3]))
List Syntax¶
[] # empty list
[1, 2, 3] # three elements
[HEAD, *TAIL] # head/tail destructuring (like Prolog [H|T])
[A, B, *REST] # first two elements + rest
Clause heads can describe list structure using [HEAD, *TAIL], relating the
whole list to its parts (see Syntax for the full pattern language):
Membership¶
in_/2¶
in_(Elem, List) — the membership relation. Holds for each element in List
on backtracking.
in_check/2¶
in_check(Elem, List) — deterministic membership. Holds at most once (first
unifying element only). Use when you need to confirm membership without
enumerating alternatives.
Building & Joining¶
append/3¶
append(L1, L2, L3) — relates three lists such that L3 is L1 followed by
L2. Works in all directions:
# Concatenate
Test("concat") <- append([1, 2], [3, 4], [1, 2, 3, 4])
# Split — enumerate all ways to split a list
Test("split") <- (
append(LEFT, RIGHT, [1, 2, 3]),
LEFT == [1],
RIGHT == [2, 3]
)
# Suffix extraction
Test("suffix") <- append([1, 2], REST, [1, 2, 3, 4, 5])
replicate/3¶
replicate(N, Elem, List) — List is N copies of Elem.
zip_/3¶
zip_(L1, L2, Pairs) — pair up corresponding elements. Stops at the shorter
list.
Access & Slicing¶
length/2¶
length(List, N) — relates a list to its length. Can also generate a list of
N fresh variables.
list_item/3¶
list_item(N, List, Elem) — relates a 0-based index, a list, and an element.
Test("get") <- list_item(1, ["a", "b", "c"], "b")
Test("enumerate") <- (list_item(I, [10, 20, 30], 20), I == 1)
last/2¶
last(List, Elem) — the last element.
take/3¶
take(N, List, Taken) — first N elements.
drop/3¶
drop(N, List, Rest) — everything after the first N elements.
split_at/4¶
split_at(N, List, Left, Right) — split at index N.
Reordering¶
reverse/2¶
reverse(List, Rev) — reverse a list.
sort/2¶
sort(List, Sorted) — sort and remove duplicates.
msort/2¶
msort(List, Sorted) — sort preserving duplicates.
permutation/2¶
permutation(List, Perm) — the permutation relation. Holds for each
permutation of List on backtracking.
flatten/2¶
flatten(List, Flat) — recursively flatten nested lists.
Selection¶
select/3¶
select(Elem, List, Rest) — relates an element, a list containing it, and
the list without it. Holds for each element on backtracking.
This is useful for constraint-style problems where you need to choose from a pool:
assign([], []),
assign([SLOT, *SLOTS], POOL) <- (
select(CHOICE, POOL, REMAINING),
SLOT == CHOICE,
assign(SLOTS, REMAINING)
)
split_with/3¶
split_with(Sep, List, Parts) — split a list by separator value, or join parts
with a separator.
Set Operations¶
These operate on plain lists, treating them as sets.
list_to_set/2¶
list_to_set(List, Set) — remove duplicates, preserving order.
union/3¶
union(S1, S2, Result) — elements in either set, no duplicates.
intersection/3¶
intersection(S1, S2, Result) — elements in both sets.
subtract/3¶
subtract(S1, S2, Result) — elements in S1 but not in S2.
Aggregation¶
sum_list/2¶
sum_list(List, Total) — sum all numbers in a list.
max_list/2¶
max_list(List, max_) — maximum element.
min_list/2¶
min_list(List, min_) — minimum element.
Patterns & Recipes¶
Rotate a list¶
partition by predicate¶
Using Call/N to apply a predicate argument:
Partition([], _, [], []) <- True
Partition([X, *XS], PRED, [X, *YES], NO) <- (
call(PRED, X),
Partition(XS, PRED, YES, NO)
)
Partition([X, *XS], PRED, YES, [X, *NO]) <- (
not call(PRED, X),
Partition(XS, PRED, YES, NO)
)
Sliding window¶
Gotchas¶
sortremoves duplicates — usemsortif you need to keep them.list_itemis 0-based — unlike Prolog'snth1which is 1-based.in_yields multiple solutions — if you only need to confirm membership once, usein_check.flattenis fully recursive —[1, [2, [3]]]becomes[1, 2, 3], not[1, 2, [3]].
See also: Strings as Lists — strings behave as character lists, Pairs — key-value pair operations, Higher-Order — maplist, include, foldl over lists, Dicts & Sets — dictionary and set data structures.