Shen contains a Prolog, just as Qi II, but the m-prolog syntax has been dropped.
The main reason for this was that embedding executable code in a string (to preserve conformancy
with Edinburgh syntax ) generated awkward anomalies with respect of the rest of the system. For
example a special string searching routine had to be developed for m-prolog declarations embedded
in a package; symbol overloading had to be used because Edinburgh Prolog uses '=' to mean something
different from simple equality; you cannot insert comments inside an m-prolog program and searching
in an m-prolog program is more difficult since the structure is in a string not a list. To compensate
Qi developed a low level s-prolog convention in which Prolog programs were s-exprs.
In place of the awkward dual convention, Shen has one Prolog notation consistent with the
rest of Shen which uses 'defprolog'. Here are the member, reverse and append functions in Shen Prolog.
X [X | _] <--;
X [_ | Y] <-- (member X Y);)
  <--;
[X | Y] Z <-- (rev Y W) (conc W [X] Z);)
 X X <--;
[X | Y] Z [X | W] <-- (conc Y Z W);)
The following functions are found in Shen Prolog
predicate || arity || description |
asserta || 1 || succeeds and the clause is asserted into Prolog. |
assertz || 1 || succeeds and the clause is asserted into Prolog. |
dynamic || _ || used outside Prolog, makes a predicate dynamic and capable of receiving asserta/z and retract. |
var? || 1 || succeeds if the term is a Prolog variable |
is || 2 || unifies the first term to the second without an occurs check |
is! || 2 || unifies the first term to the second with an occurs check |
findall || 3 || takes a variable X , a literal L and a variable Y and finds all values for X in L
for which L is provable and binds the list of these values to Y. (findall X (woman X) Y) will find
all values for X for which (woman X) is provable and bind the result to Y. |
when || 1 || the term is evaluated to true or false and the call succeeds if it is true. All variables
in the term are completely dereferenced. |
call || 1 || apply the predicate at the head of the list to the terms of the tail. (Prolog apply) |
return || 1 || terminate Prolog returning the dereferenced value of the term. |
! || 0 || Prolog cut |
fork || 1 || fork does the job of the semi-colon in Edinburgh Prolog; it succeeds if one of the literals
in the following list succeeds. |
receive || 1 || bind a variable to a value outside of Prolog |
retract || 1 || succeeds and the clause is retracted from Prolog. |
Both 'findall' and 'call' were revised in the S series kernels to take applications and not lists.
(41-) (defprolog mymap
F   <--;
F [X | Y] [W | Z] <-- (call (F X W)) (mymap F Y Z);)
(42-) (defprolog ab
a b <--;
X X <--;)
(43-) (prolog? (mymap (fn ab) [a a a] X) (return X))
[b b b]
'fork' was introduced in the S series kernels.
X <-- (g X) (h X);
X <-- (g X) (i X);
X <-- (g X) (j X);)
can be coded as
X <-- (g X) (fork (h X) (i X) (j X));)
'receive' was introduced in version 14 to allow Prolog to be called with a variable whose binding is
made outside Prolog. Thus '(foo a)' in
X -> (prolog? (bar (receive X) (receive X))))
will call '(bar a a)' inside Prolog.
Here is assert and retract.
(0-) (dynamic male)
(1-) (defprolog male
(2-) (prolog? (asserta [[male bill] <--;]))
(3-) (prolog? (male bill))
(4-) (prolog? (retract [[male bill] <--;]))
(5-) (prolog? (male bill))
Mode declarations suspend unification in favour of pattern-matching and are used only
in the head of a clause. Thus
(- a) <--;)
enforces a strict match between the argument a and the input to f. The default mode is unification signalled by +.
Mode declarations can be nested as in (- [f a (+ b)]). In this event the innermost declaration has priority. The
above expression would thus perform pattern-matching with respect to all its elements save b which would receive
unification. The abbreviated notation was introduced in the S series kernels; '(mode a -)' will still compile.