Пролог: определение операторов логики высказываний и добавление аргументов в список - PullRequest
0 голосов
/ 13 октября 2019

Я пытаюсь определить некоторые операторы, которые добавляют операторы с аргументами и одинокими аргументами в список.

До сих пор я определил два оператора, которые я собираюсь использовать, которые являются ИЛИи ОТРИЦАНИЕ, но я не знаю, как определить действия, которые они должны делать дальше, которые создают списки и добавляют к нему операторы и аргументы.

:- op(400,fx,neg).
:- op(500,xfx,or).

После этого я не уверено том, как добавить операторы и аргументы в список и создать объединение всех списков. В соответствии с инструкцией объединения в руководстве это будет примерно так:

neg(X,[]) :- union([X],[neg(X)],[]).
or(X,Y,[]) :- union([X],[or(X,Y)],[]).
or(X,Y,[]) :- union([Y],[or(X,Y)],[]).

, который не отправляет никаких ошибок, но как мне сделать объединение всех списков и как указать, что любойдля ввода может использоваться строчная буква.

Примером импульса будет:

neg(a or b).

И ожидаемый результат:

[neg(a or b), a or b, a, b]

1 Ответ

0 голосов
/ 14 октября 2019

Вы столкнулись с интересной глобальной вещью о Prolog, которую операторы действительно выводят на поверхность, а именно то, что операторы - это просто еще один способ построения терминов.

Эти ваши определения операторов позволяют создавать терминыс другой стороны, например:

?- X = neg a or b.
X = neg a or b.

Наделение этих терминов значением , с другой стороны, потребует от вас создания другого предиката. Это связано с тем, что термины в Прологе не являются выражениями, которые сокращаются сами по себе - отчасти поэтому вам нужно использовать is/2, чтобы уменьшить арифметическое выражение до значения. Даже чисто арифметические вещи - это просто термины в Прологе:

?- X = 16*3 + 4.
X = 16*3+4.

Это не какое-то особенное поведение =/2 в Прологе. Так устроены условия. Для уменьшения значения требуется развертывание другого предиката:

?- X is 16*3+4.
X = 52.

Итак, вы, похоже, сделали, что ваш оператор neg вызвал предикат с двумя аргументами для его уменьшения и что ваш оператор or имеетвызвал предикат из трех аргументов для его уменьшения. На самом деле ничего из этого не произошло, все, что делают ваши операторские объявления, это позволяет вам создавать термины, подобные приведенному выше, neg a or b. Таким образом, вам все еще нужно создать отдельный предикат для их оценки, где ваша семантика входит в картину. Итак, давайте реализуем предикат eval/2, который преобразует ваш термин в требуемое значение результата:

eval(neg X, [neg X|Result])   :- 
    eval(X, Result).

eval(X or Y, [X or Y|Result]) :- 
    eval(X, R1), 
    eval(Y, R2), 
    append(R1, R2, Result).

eval(X, [X]) :- atomic(X).

Ключевая идея здесь состоит в том, чтобы соответствовать тому, что дают ваши операторы, и рекурсивно снимать по одному слою за раззову остальных. Наш базовый случай - это «атомные значения», то есть атомы типа a.

. Это дает нам то, что вы ищете:

?- eval(neg (a or b), R).
R = [neg (a or b), a or b, a, b] 

Обратите внимание, что is/2 являетсяоператор. Вы также можете определить оператор, который «работает», объявив оператора, а затем предоставив правила для его приложения. Это не поможет вам в этом случае, потому что ваши примеры для neg и or требуют, чтобы вы сохранили структуру, а не отбросили ее. is/2, с другой стороны, предполагает, что структура существует в правом аргументе, и уменьшает ее до значения для левого. Вы можете сделать что-то подобное, например, сделав eval/2 оператором, и в этом случае оператор будет использоваться слева от :-, например, так:

[Neg X|R] eval (neg X) :- R eval X.

Однако я нахожу этот видтрудно обрабатывать и определенно избегать этого, если это не приведет к большей ясности.

Кстати, вы, скорее всего, захотите заменить xfx в своем вызове op/3 на xfy или yfx, поскольку конструкции типа a or b or c не будут работать с xfx из-за конфликта приоритетов оператора. С xfy он будет проанализирован как a or (b or c), а с yfx он будет проанализирован как (a or b) or c, что, вероятно, более полезно. А также, если вы намереваетесь всегда заключать в скобки то, с чем вы используете neg, тогда вам не нужно объявлять оператор для него - цель унарного оператора состоит в том, чтобы просто пропустить парены(и контролируйте, сколько из того, что следует, потребляется им.)

Надеюсь, это поможет!

...