Соответствие кортежам в Прологе

Почему Пролог соответствует (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

На самом деле это - то, чего я хочу достигнуть, но это кажется подозрительным. Там какой-либо другой путь состоит в том, чтобы рассматривать соединение условий с должности списка в Прологе?

1
задан milosz 23 May 2010 в 22:32
поделиться

2 ответа

Конструкция

кортежа 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]).
2
ответ дан 3 September 2019 в 00:21
поделиться

Хмм ... 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.
0
ответ дан 3 September 2019 в 00:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: