We use these rules like so,
4 ?- phrase(move(X), [up,up,down,up,up]).
X = move(step(up), move(step(up), move(step(down), move(step(up),
move(step(up)))))) ;
false.
5 ?- meaning($X,N).
N = 3 ;
false.
The term produced is highly nested:
move(step(up), % move/2: step/1 ,
move(step(up), % move/2: step/1 ,
move(step(down), % move/2: step/1 ,
move(step(up), % move/2: step/1 ,
move(step(up)))))) % move/1: step/1 .
The code that you ask about, strips away the functors from the compound terms, getting to the "meat" of it, i.e. up
or down
atom arguments:
(2) meaning(step(Step), Dist):- meaning(Step, Dist).
"to find the ''meaning'' of a unary compound term step(X)
, is the same as to find the ''meaning'' of X
".
(3) meaning(move(Step), Dist):- meaning(Step, Dist).
"to find the ''meaning'' of a unary compound term move(X)
, is the same as to find the ''meaning'' of X
".
(4) base cases: ''meaning'' is given as 1
or -1
for up
or down
atoms.
meaning(step(up), 1). % clashes with rule (2)
meaning(step(down), -1). % clashes with rule (2)
(1) And the main case deals with binary compound terms with the functor move
:
meaning(move(Step, Move), Dist):-
meaning(Step, D1),
meaning(Move, D2),
Dist is (D1 + D2).
move/2
is a custom version of (non-empty) list, '.'/2
, actually:
1 ?- write_canonical([1,2,3]).
'.'(1,'.'(2,'.'(3,[])))
true.
2 ?- write_canonical([step(up),step(down),step(up)]).
'.'(step(up),'.'(step(down),'.'(step(up),[])))
true.
And meaning/2
is a fold.