Почему Пролог соответствует (X, Xs) с кортежем, содержащим больше элементов? Пример:
test2((X, Xs)) :- write(X), nl, test2(Xs).
test2((X)) :- write(X), nl.
test :-
read(W),
test2(W).
?- test.
|: a, b(c), d(e(f)), g.
a
b(c)
d(e(f))
g
yes
На самом деле это - то, чего я хочу достигнуть, но это кажется подозрительным. Там какой-либо другой путь состоит в том, чтобы рассматривать соединение условий с должности списка в Прологе?
кортежа term с оператором ,/2
в PROLOG является в общем случае право-ассоциативной (обычно называемой sequence), Так что ваш ввод a, b(c), d(e(f)), g
вполне может быть на самом деле термином (a, (b(c), (d(e(f)), g)))
. Об этом свидетельствует тот факт, что ваш предикат test2/1
напечатал то, что показано в вашем вопросе, где при первом вызове первого пункта test2/1
, X
соответствовал a
, а Xs
соответствовал (b(c), (d(e(f)), g))
, затем при втором вызове X
соответствовал b(c)
и Xs
соответствовал (d(e(f)), g)
, и так далее.
Если бы вы действительно хотели иметь дело со списком терминов, интерпретируемых как конъюнкция, вы могли бы использовать следующее:
test2([X|Xs]) :- write(X), nl, test2(Xs).
test2([]).
...на входе [a, b(c), d(e(f)), g]
. Структура списка здесь обычно интерпретируется несколько иначе, чем кортежи, построенные с помощью ,/2
(поскольку, по крайней мере в SWI-PROLOG, такие структуры являются синтаксическим сахаром для работы с терминами, построенными с помощью ./2
, точно так же, как вы строите последовательности или кортежи с помощью ,/2
). Таким образом, вы получаете преимущества поддержки терминов списков, если вы можете позволить терминам списков быть интерпретированными как конъюнкции в вашем коде. Другая альтернатива - объявить и использовать свой собственный (возможно, инфиксный оператор) для конъюнкции, например &/2
, который можно объявить как:
:- op(500, yfx, &). % conjunction constructor
Затем вы можете построить конъюнкцию как a & b(c) & d(e(f)) & g
и работать с ней соответствующим образом, точно зная, что вы подразумеваете под &/2
- конъюнкцией.
Смотрите страницу руководства для op/3
в SWI-PROLOG для более подробной информации - если вы не используете SWI, я предполагаю, что должен быть аналогичный предикат в любой реализации PROLOG, которую вы используете - если она стоит своей соли:
EDIT: Чтобы преобразовать кортеж, построенный с помощью ,/2
в список, вы можете использовать что-то вроде следующего:
conjunct_to_list((A,B), L) :-
!,
conjunct_to_list(A, L0),
conjunct_to_list(B, L1),
append(L0, L1, L).
conjunct_to_list(A, [A]).
Хмм ... a, b (c), d (e (f)), g
означает a
и ( b (c)
и ( d (e (f))
и g
)), а также list [1,2,3]
- это просто [1 | [2 | [3 | []]]]
. Т.е. если вы превратите это соединение в список, вы получите тот же test2 ([X | Xs]): -...
, но разница в том, что соединение несет информацию о том, как эти две цели объединены (там также может быть дизъюнкцией (X; Xs)
). И вы можете построить другую иерархию союзов с помощью (a, b (c)), (d (e (f)), g)
Вы работаете с простыми рекурсивными типами. В других языках списки также являются рекурсивными типами, но они часто притворяются массивами (большие-большие кортежи с хорошей индексацией).
Вероятно, вам следует использовать:
test2((X, Y)):- test2(X), nl, test2(Y).
test2((X; Y)). % TODO: handle disjunction
test2(X) :- write(X), nl.