
member(X,[X|_]). member(X,[_|T]) :- member(X,T).
Goal
member(mary, [john, mary, pat]).
X can't be both mary and johnX = mary, _ = john, T = [mary, pat]member(mary, [mary, pat])
X = mary, _ = pattrue.member(X,[_|T]) and member(mary, [john, mary, pat])X = mary, _ = john, T = [mary, pat]| Equation | Action |
| f(s1, ..., sn) = f(t1, ..., tn) | Replace with s1 = t1, ..., sn = tn |
| f(s1, ..., sn) = g(t1, ..., tn) where f ≠ g | Halt with failure |
| X = X | Delete the equation |
| t = X where t is not a variable | Replace with X = t |
| X = t where X does not occur in t and it occurs elsewhere | Apply the substitution X = t to all other terms |
| X = t where X occurs in t (but t ≠ X) | Halt with failure |
member(X,[_|T])= member(mary, [john, mary, pat])[ | ] as consmember(X, cons(Z, T))= member(mary, cons(john, cons(mary, cons(pat, nil))))X = marycons(Z, T) = cons(john, cons(mary, cons(pat, nil)))X = maryZ= johnT = cons(mary, cons(pat, nil))parent(james1, charles1). parent(charles1, charles2). parent(charles1, catherine). parent(charles1, james2). grandparent(X, Y) :- parent(X, Z), parent(Z, Y).
Query: grandparent(james1, G)
X = james1, Y = Gparent(james1, Z) parent(Z, G)
Z = charles1parent(charles1, G)
parent(Z, Y) / X = james1, Y = G, Z = charles1
parent(charles1, G)parent(james1, charles1). parent(charles1, charles2). parent(charles1, catherine). parent(charles1, james2).
charles1 ≠ james1)G = charles2G = catherineancestor(X, Z) :- parent(X, Y), ancestor(Y, Z). ancestor(X, Y) :- parent(X, Y).
Query: ancestor(james1, X)
ancestor(james1, X) with ancestor(X, Z)Xancestor(james1, X) and ancestor(X1, Z)X1 = james1, X = Zparent(X1, Y) / X1 = james1, X = Z ancestor(Y, Z) / X1 = james1, X = Z
Y = charles1ancestor(Y, Z). Unify with ancestor(X, Z). ancestor(X2, Z1)
member(X, cons(john, cons(mary, nil))) member(X17, cons(X17, T))
Compute a unifying substitution (by hand). What is it?
member(X, cons(john, cons(mary, nil)))
and the clause
member(X, cons(X, T)) :- member(X,T).
Compute a unifying substitution of the goal and the head of the clause after renaming variables in the clause. What is it?
Save this Prolog.scala file and load it into Eclipse.
Note these commands in Main.main:
import Prolog._
val member = new Predicate
member('X, 'X::'Xs)!
member('X, 'Y::'Ys) :- member('X, 'Ys)
member('X, 'john :: 'mary :: 'nil)?
more
more
As you can see, the implementor of this interpreter cleverly overloaded operators ! (fact), :- (provided that) and ? (query).
Note the single quote that is used for variables.
Now change Main.main to
...
showMatches = true
member('X, 'john :: 'mary :: 'nil)?
more
more
What output do you get?
Now comes the hard part: Put together a complete trace of what the interpreter does. In each step, you can choose from
Use the same substitution that the Scala interpreter uses. When I ran it, the trace output started with
unify 'X with 'john = true unify 'X16 with 'john = true unify 'Xs17 with 'mary :: 'nil = true
My solution would be
Step 1. Push member(X, cons(john, cons(mary, nil))) on goal stack
Step 2. Choose rule member(X, cons(X, Xs)).
Step 3. Rename into member(X16, cons(X16, Xs17)).
Step 4. Use unification: X = X16, john = X16, Xs17 = cons(mary, nil) solves as X = john, X16 = john, Xs17 = cons(mary, nil).
Step 5. Unification with fact was success. Display result.
Step 6. Choose rule member(X, cons(Y, Ys)) :- member(X, Ys).
...