Просто вызовите scanf ("% * [^\n]\n") внутри цикла и отбросит «кеш».
Если вы хотите более краткое решение, используя maplist/2
, вы можете сделать что-то вроде:
isTwo(2) :- write('Yes'), !.
isTwo(_):- write('No').
test(L):-
maplist(isTwo,L).
?- test([1,3,3,2,2,7,2,9]).
NoNoNoYesYesNoYesNo
true
test/1
не является обязательным, я добавил его только для ясности ...
Что ж, простым решением было бы использование второй переменной в iter
, которая поможет вам понять, если найдено число, отличное от 2:
isTwo(2, X, X) :-
write('Yes').
isTwo(_, _, 0) :-
write('No').
iter([], 0):- fail,!.
iter([], 1).
iter([Head|Tail], X) :-
isTwo(Head, X, Y),
iter(Tail, Y).
iter(L) :- iter(L, 1).
Другие ответы тоже хороши, но случайное смешение побочных эффектов заставляет меня немного нервничать. Кроме того, у вас есть проблема, если список, который вы «анализируете», имеет свободную переменную (она станет 2
молча).
Почему бы не так:
is_two(X) :- X == 2, !, format("Yes").
is_two(X) :- X \== 2, !, format("No").
, а затем:
?- forall(member(X, [1,3,3,2,2,7,2,9]), is_two(X)).
NoNoNoYesYesNoYesNo
true.
?- forall(member(X, [Y, 2, Z]), is_two(X)).
NoYesNo
true.
Используйте ==
и \==
для сравнения без объединения. Используйте forall
и member
, чтобы прояснить, что вы делаете это для побочного эффекта. Обход списка (или использование maplist
) немного обманывает.
forall
- это просто более ясный способ сделать цикл, управляемый отказом, используя отрицание вместо сокращений и неудач. Вышеприведенный запрос идентичен:
?- \+ ( member(X, [1,3,3,2,2,7,2,9]), \+ is_two(X) ).