Конструкция
Tuple 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, которую вы используете - - если оно того стоит, то соль: -)
РЕДАКТИРОВАТЬ: Чтобы преобразовать термин кортеж, построенный с использованием ,/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]).