Вопрос по – Пролог - необычный минус синтаксиса для списков

27

Я наткнулся на незнакомый фрагмент синтаксиса Пролога в статье Ли Наиша.Логическое программирование высшего порядка в Прологе, Вот первый пример кода из статьи:

<code>% insertion sort (simple version)
isort([], []).
isort(A.As, Bs) :-
    isort(As, Bs1),
    isort(A, Bs1, Bs).

% insert number into sorted list
insert(N, [], [N]).
insert(N, H.L, N.H.L) :-
    N =< H.
insert(N, H.LO, H.L) :-
    N > H,
    insert(N, LO, L).
</code>

Моя путаница сA.As вisort(A.As, Bs) :-, Из контекста, этоappears быть альтернативным синтаксисом для списков, эквивалентisort([A|As], Bs) :-.

ТакжеN.H.L представляется более удобным способом сказать[N|[H|L]].

Но SWI Prolog не примет этот необычный синтаксис (если я не делаю что-то не так).

Кто-нибудь это признает? моя гипотеза верна? Какой интерпретатор Prolog принимает это как действительный синтаксис?

Я отсканировал бумагу для этого, но, к сожалению, там не было ссылки на нее! Nick Knowlson
Какой Пролог используется в статье? Chetter Hummin
Это может быть просто синтаксический сахар Chetter Hummin

Ваш Ответ

3   ответа
9

Этот синтаксис происходит от NU-Prolog. УвидетьВот, Это, вероятно, просто обычный функтор списка. / 2 переопределен как инфиксный оператор, без необходимости использовать конечный пустой список:

?- L= .(a,.(b,[])).
L = [a,b]
Yes (0.00s cpu)
?- op(500, xfy, '.').
Yes (0.00s cpu)
?- L = a.b.[].
L = [a,b]
Yes (0.00s cpu)
@false: спасибо, высоко ценится.
@false: делает меня любопытным. Можете ли вы указать какие-либо ссылки, которые легко доступны? Я никогда не видел, чтобы он использовался как инфиксный оператор где-либо еще. Не могу вспомнить, например, когда видел это в C & amp; M.
Я добавил наиболее заметную ссылку на мой ответ.
Синтаксис намного старше, чем NU (1987) или MU.
33

Точечный оператор использовался для списков в самой первой системе Пролог 1972 года, написанной на Algol-W, иногда называемой Пролог 0. Он основан на аналогичной записи в системах LISP. Следующий пример из бумагиРождение Пролога Ален Колмерауэр и Филипп Руссель & # x2013; сами создатели пролога.

+ELEMENT(*X, *X.*Y).
+ELEMENT(*X, *Y.*Z) -ELEMENT(*X, *Z).

В это время,[] раньше былNIL.

Следующая версия Пролога, написанная на Фортране Battani & amp; Мелони, использовал случаи, чтобы различать атомы и переменные. Затем DECsystem 10 Prolog представила квадратную скобку, заменяющую нотациюnil а такжеX.Xs с[] а также[X,..Xs] который в более поздних версиях DECsystem 10 получил[X|Xs] как альтернатива. В ISO Prolog есть только[X|Xs], .(X,Xs)и как канонический синтаксис'.'(X,Xs).

Обратите внимание, что у точки есть много разных r & # xF4; файлов в ISO Prolog. Это уже служит

  • end token when followed by a % or a layout character like SPACE, NEWLINE, TAB.

  • decimal point in a floating point number, like 3.14159

  • graphic token char forming graphic tokens as =..

Так что если вы сейчас заявляете. как инфиксный оператор, вы должны быть очень осторожны. И с тем, что вы пишете, и с тем, что будут читать системы Prolog. Одно дополнительное пространство может изменить значение термина. Рассмотрим два списка чисел в обоих обозначениях:

[1,2.3,4]. [5].
1 .2.3.4.[]. 5.[].

Обратите внимание, что вы должны добавить пробел после1, В этом контексте дополнительный пробел перед числом может изменить значение ваших терминов. Вот так:

[1|2.3]. [4]. 5. [].
1 .2.3. 4.[]. 5. [].

Вот еще один пример, который может быть еще более убедительным:

[1,-2].
1.(-2).[].

Отрицательные числа требуют круглых скобок в точечных списках.

Сегодня осталось только YAP и XSB, которые все еще предлагают инфикс. по умолчанию & # x2013; а такжеони делают это по-другому, А XSB даже не распознает синтаксис выше точки: вам нужны круглые скобки вокруг некоторых неотрицательных чисел.

Вы написали этоN.H.L представляется более удобным способом сказать[N|[H|L]], Существует простое практическое правило для упрощения таких выражений в ISO Prolog: всякий раз, когда вы видите в списке токены| а также[ сразу после друг друга, вы можете заменить их на, (и удалите соответствующий] на правой стороне). Теперь вы можете написать:[N,H|L] который не выглядитthat плохой.

Вы можете использовать это правило и в другом направлении. Если у нас есть список[1,2,3,4,5] мы можем использовать| в качестве «лезвия бритвы»; вот так:[1,2,3|[4,5]].


Еще одно замечание, поскольку вы читаете статью Наиша:понятно хорошо только этоcall/N нужно! И ISO Prolog поддерживаетcall/1, call/2 вплоть доcall/8.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededhow lambdas fit with call/N.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededcs.unm.edu/~luger/cs451/resources/recursive.pdfError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded[N,H|L]Error: User Rate Limit Exceeded Nick Knowlson
10

Да, вы правы, точка это списокcons инфиксный оператор. Это фактически требуется стандартом ISO Prolog, но обычно скрыто. Я нашел (и использовал) этот синтаксис некоторое время назад:

:- module(eog, []).
:- op(103, xfy, (.)).

% where $ARGS appears as argument, replace the call ($ARGS) with a VAR
% the calle goes before caller, binding the VAR (added as last ARG)
funcs(X, (V, Y)) :-
    nonvar(X),
    X =.. W.As,

    % identify meta arguments
    (   predicate_property(X, meta_predicate M)
        % explicitly exclude to handle test(dcg)
        % I'd like to handle this case in general way...
    ,   M \= phrase(2, ?, ?)
    ->  M =.. W.Ms
    ;   true
    ),

    seek_call(As, Ms, Bs, V),
    Y =.. W.Bs.

% look for first $ usage
seek_call([], [], _Bs, _V) :-
    !, fail.
seek_call(A.As, M.Ms, A.Bs, V) :-
    M @>= 0, M @=< 9, % skip meta arguments
    !, seek_call(As, Ms, Bs, V).
seek_call(A.As, _, B.As, V) :-
    nonvar(A),
    A = $(F),
    F =.. Fp.FAs,
    (   current_arithmetic_function(F) % inline arith
    ->  V = (PH is F)
    ;   append(FAs, [PH], FBs),
        V =.. Fp.FBs
    ),
    !, B = PH.
seek_call(A.As, _.Ms, B.As, V) :-
    nonvar(A),
    A =.. F.FAs,
    seek_call(FAs, Ms, FBs, V),
    !, B =.. F.FBs.
seek_call(A.As, _.Ms, A.Bs, V) :-
    !, seek_call(As, Ms, Bs, V).

:- multifile user:goal_expansion/2.
user:goal_expansion(X, Y) :-
    ( X = (_ , _) ; X = (_ ; _) ; X = (_ -> _) )
    -> !, fail % leave control flow unchanged (useless after the meta... handling?)
    ;  funcs(X, Y).

/* end eog.pl */

Мне посоветовали против этого. Фактически, синтаксис [A | B] - это эволюция. оператор, введенный для удобства чтения.

OTЧто это за код?

приведенный выше код - моя попытка подсластить Пролог функциями. А именно, вводит по запросу, с помощью$временные переменные, требуемые (например) арифметическими выражениями

fact(N, F) :-
     N > 1 -> F is N * $fact($(N - 1)) ; F is 1.

каждый $ вводит переменную. После расширения мы имеем более традиционный факт / 2

?- listing(fact).
plunit_eog:fact(A, C) :-
    (   A>1
    ->  B is A+ -1,
        fact(B, D),
        C is A*D
    ;   C is 1
    ).

Там, где у нас много выражений, это может быть полезно ...

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded$Error: User Rate Limit Exceeded$factError: User Rate Limit Exceeded Nick Knowlson
Error: User Rate Limit Exceededgoal_expansion/2Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededexistingError: User Rate Limit ExceededThere is progressError: User Rate Limit Exceeded

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