1:- module(swi_compounds, [flatten_slashes/2, append_path/3]).
mode(+, ?)
. Fails if Components do not match the
incoming Components0 correctly with the same number of slashes.
Consecutive slash-delimited compound terms decompose in Prolog as
nested slash-functors. Compound a/b/c
decomposes to /(a/b, c)
for example. Sub-term a/b
decomposes to nested /(a, b)
. The
predicate converts any /(a, b/c)
to /(a/b, c)
so that the
shorthand flattens from a/(b/c)
to a/b/c
.
Note that Prolog variables match partially-bound compounds; A
matches A/(B/C)
. The first argument must therefore be fully ground
in order to avoid infinite recursion.
23flatten_slashes(Component0/(Component/Components0), Components) :- 24 !, 25 flatten_slashes(Component0/Component/Components0, Components). 26flatten_slashes(Components0/Component, Components/Component) :- 27 !, 28 flatten_slashes(Components0, Components). 29flatten_slashes(Component, Component).
append_path(A, B/5, 1/2/3/4/5)
gives one solution
of A = 1/2/3 and B = 4.
There is an implementation subtlety. Only find the Right hand key if the argument is really a compound, not just unifies with a slash compound since Path/Component unifies with any unbound variable.
45append_path(Left, Right0, LeftAndRight/Component) :- 46 compound(Right0), 47 !, 48 compound_name_arguments(Right0, /, [Right, Component]), 49 append_path(Left, Right, LeftAndRight). 50append_path(Left, Right, Left/Right) :- !. 51append_path(Left, Right/Component, LeftAndRight/Component) :- 52 append_path(Left, Right, LeftAndRight)