I can't quite seem to wrap my head around some of the behaviour of prolog (gprolog). As some background, rotate is supposed to compare two lists and see if they have been shifted (As below).
?- rotate(1,[4,1,2,3],[1,2,3,4]).
should return true. However, prolog doesn't seem to be respecting the rule ordering when the above question is asked.
rotate(0,[],[],[]).
%base case
rotate(0,[],[H|T1],[H|T2]):- rotate(0,[],T1,T2).
%recurse over the remainder list (the first list from S to the end)
Prolog will ignore the predicate directly below when
rotate(S,[H|T1],[H|T2],L):-S=:=0,rotate(0,T1,T2,L).
%recurse over the elements from S to the end of list1
backtracking from this other predicate (directly below).
rotate(S,[H|T1],L,T2):-S > 0,S1 is S - 1,rotate(S1,T1,L,[H|T2]).
%add elements 1 to S into the remainder list
rotate(S,L1,L2):-len(L1,Len),S1 is S mod Len,!,rotate(S1,L1,L2,[]).
%ensure the shift is not out of bounds, call rotate/4
%utility function because couldn't use length
len([],Ret,Ret).
len([_|T],Len,Ret):-Len1 is Len+1,len(T,Len1,Ret).
len(L,Len):-len(L,0,Len).
I discovered this behaviour by tracing it, and am frankly perplexed as to why it won't backtrack and hit the next predicate, instead it fails and returns false.
I'm also open to better ways to do this, since it's practise for a midterm.