/***************************/ /* */ /* Answers to worksheet 15 */ /* */ /***************************/ /* Exercise 15.1 Max */ /* In the given program, the cut is green: it can be omitted without */ /* changing the meaning of the program. */ /* Changing it to a red cut: */ max(X, Y, X) :- X >= Y, !. max(X, Y, Y). /* This red cut version is wrong on the following goal: */ /* ?- max(2, 1, 1). */ /* for which it returns yes. */ /* The third version is completely wrong: the cut is in the wrong place. */ /* Irrespective of the arguments, the cut commits Prolog to the first */ /* clause. Hence, on this version, we get the following behaviour: */ /* ?- max(2, 1, M). */ /* M = 2 (correct!) */ /* ?- max(1, 2, M). */ /* no (wrong!) */ /* Exercise 15.2 Member */ /* The original version of member was non-determinstic: it could find all */ /* occurrences of an item in the list. This is most apparent when asking it */ /* to enumerate items of a list: */ /* ?- member(X, [a, b, c]). */ /* X = a ; */ /* X = b ; */ /* X = c ; */ /* no */ /* The version with the cut is deterministic and will only find the first */ /* occurrence of an item in a list. Enumeration no longer works: */ /* ?- member(X, [a, b, c]). */ /* X = a ; */ /* no */ /* Exercise 15.3 Split */ /* split1: cut-free */ split1([], [], []). split1([PosN|Ns], [PosN|Pos], Neg) :- PosN >= 0, split1(Ns, Pos, Neg). split1([NegN|Ns], Pos, [NegN|Neg]) :- NegN < 0, split1(Ns, Pos, Neg). /* split2: green cut */ split2([], [], []) :- !. split2([PosN|Ns], [PosN|Pos], Neg) :- PosN >= 0, !, split2(Ns, Pos, Neg). split2([NegN|Ns], Pos, [NegN|Neg]) :- NegN < 0, split2(Ns, Pos, Neg). /* split3: red cut */ split3([], [], []) :- !. split3([PosN|Ns], [PosN|Pos], Neg) :- PosN >= 0, !, split3(Ns, Pos, Neg). split3([NegN|Ns], Pos, [NegN|Neg]) :- split3(Ns, Pos, Neg). /* Exercise 15.4 If then else */ if_then_else(P, Q, R) :- call(P), !, call(Q). if_then_else(P, Q, R) :- call(R).