使用nth1/3的参数顺序
nth1_once_else_0(Nth1, Lst, Elem) :-
nth1_once_else_0_thaw_(Lst, Elem, 1, Nth1).
nth1_once_else_0_thaw_(L, _Elem, _Upto, Nth1) :-
L == [],
!,
Nth1 = 0.
nth1_once_else_0_thaw_(L, Elem, _Upto, Nth1) :-
Nth1 == 0,
!,
nth1_once_else_0_thaw_0_(L, Elem).
nth1_once_else_0_thaw_([H|_], Elem, Upto, Nth1) :-
Upto == Nth1,
!,
H = Elem.
nth1_once_else_0_thaw_(_L, _Elem, Upto, Nth1) :-
% If gone past Nth1, fail
nonvar(Nth1),
Nth1 =< Upto,
!,
fail.
nth1_once_else_0_thaw_(L, Elem, Upto, Nth1) :-
var(L),
var(Nth1),
% Too little info
!,
when(
(nonvar(L) ; nonvar(Nth1)),
nth1_once_else_0_thaw_(L, Elem, Upto, Nth1)
).
nth1_once_else_0_thaw_(L, _Elem, _Upto, Nth1) :-
L == [],
!,
Nth1 = 0.
nth1_once_else_0_thaw_([H|_], Elem, Upto, Nth1) :-
ground(Elem),
ground(H),
H = Elem,
!,
% Elements match
Upto = Nth1.
nth1_once_else_0_thaw_([H|T], Elem, Upto, Nth1) :-
( nonvar(Nth1),
Nth1 > Upto -> true
; + subsumes_term(H, Elem)
),
!,
% Elements must be different
dif(H, Elem),
Upto1 is Upto + 1,
nth1_once_else_0_when_(T, Elem, Upto1, Nth1).
nth1_once_else_0_thaw_([H|T], Elem, Upto, Nth1) :-
% Wait for ground variables
when(
(ground(H), ground(Elem) ; nonvar(Nth1)),
nth1_once_else_0_thaw_([H|T], Elem, Upto, Nth1)
).
nth1_once_else_0_when_(L, Elem, Upto, Nth1) :-
var(L),
!,
when(
(nonvar(L), nonvar(Elem) ; nonvar(Nth1)),
nth1_once_else_0_thaw_(L, Elem, Upto, Nth1)
).
nth1_once_else_0_when_([], _Elem, _Upto, 0).
nth1_once_else_0_when_([H|T], Elem, Upto, Nth1) :-
when(
(nonvar(H), nonvar(Elem) ; nonvar(Nth1)),
nth1_once_else_0_thaw_([H|T], Elem, Upto, Nth1)
).
% Remainder of list does not match
nth1_once_else_0_thaw_0_(L, Elem) :-
var(L),
!,
freeze(L, nth1_once_else_0_thaw_0_(L, Elem)).
nth1_once_else_0_thaw_0_([], _Elem).
nth1_once_else_0_thaw_0_([H|T], Elem) :-
dif(H, Elem),
freeze(T, nth1_once_else_0_thaw_0_(T, Elem)).
使用 swi-prolog 的 unit test 能力:
:- begin_tests(nth1_once_else_0).
test(1) :-
nth1_once_else_0(2, [a, b], B), B == b.
test(2) :-
nth1_once_else_0(N, [a, b, c, d, e, f, g], a), N == 1.
test(3) :-
nth1_once_else_0(N, [a, b, c, d, e, f, g], j), N == 0.
test(4) :-
nth1_once_else_0(N, [a, b, c, d, e, f, g], b), N == 2.
test(5) :-
nth1_once_else_0(N, [], a), N == 0.
test(6) :-
nth1_once_else_0(N, [], _), N == 0.
test(7) :-
nth1_once_else_0(N, [a, b, c, a, b, c], a), N == 1.
test(8) :-
+ nth1_once_else_0(6, [a, b, c, a, b, c], c).
test(9) :-
nth1_once_else_0(N, L, b), L = [a, b], N == 2.
test(10) :-
+ nth1_once_else_0(0, [a, b], b).
test(11) :-
nth1_once_else_0(N, [a, b, c, a], a), N == 1.
test(12) :-
nth1_once_else_0(N, [a, b, c], d), N == 0.
test(13) :-
nth1_once_else_0(N, [a, b], X), X = b, N == 2.
test(14) :-
nth1_once_else_0(N, L, X), L = [a, b|_], X = b, N == 2.
test(15) :-
nth1_once_else_0(N, L, X), L = [a, b|_], N = 2, X == b.
test(16) :-
nth1_once_else_0(N, L, X), L = [a, b|_], X = z, N = 0.
test(17) :-
L = [a, a], nth1_once_else_0(1, L, a), + nth1_once_else_0(2, L, a).
test(18) :-
nth1_once_else_0(N, L, X), L = [a, b|_], L = [a,b,c], N = 0, + X = a.
test(19) :-
nth1_once_else_0(N, L, X), L = [a, b|_], X = z, L = [a, b], N == 0.
test(20) :-
nth1_once_else_0(N, L, X), nth1(2, L, b), nth1(1, L, a), X = z, L = [a, b], N == 0.
test(21) :-
nth1_once_else_0(N, L, X), nth1(2, L, b), nth1(1, L, a), L = [a, b], X = a, N == 1.
test(22) :-
nth1_once_else_0(N, L, X), X = a, nth1(2, L, b), nth1(1, L, a), N == 1.
test(23) :-
nth1_once_else_0(N, L, X), X = b, nth1(2, L, b), nth1(1, L, a), N == 2.
test(24) :-
nth1_once_else_0(3, L, c), nth1(3, L, C), C == c.
test(25) :-
nth1_once_else_0(3, L, C), C = c, nth1(3, L, Z), Z == c.
test(26) :-
nth1_once_else_0(N, L, c), N = 3, nth1(N, L, C), C == c.
test(27) :-
nth1_once_else_0(N, L, C), C = c, N = 3, nth1(N, L, Z), Z == c.
test(28) :-
nth1_once_else_0(N, [a, b, c|_], c), N == 3.
test(29) :-
+ nth1_once_else_0(3, [_, _], z).
test(30) :-
nth1_once_else_0(N, [-_, -_], +_), N == 0.
:- end_tests(nth1_once_else_0).
结果:
?- run_tests.
% All 30 tests passed