Дополняя существующие ответы, я хотел бы указать несколько дополнительных моментов:
Оператор есть оператор
Во-первых, оператор =:=
, как следует из названия, является оператором. В Прологе мы можем использовать предикат current_op/3
, чтобы узнать больше об операторах. Например:
?- current_op(Prec, Type, =:=).
Prec = 700,
Type = xfx.
Это означает, что оператор =:=
имеет приоритет 700 и имеет тип xfx
. Это означает, что это бинарный оператор infix.
Это означает, что вы можете, если вы хотите, написать такой термин, как =:=(X, Y)
, эквивалентно как X =:= Y
. В обоих случаях функтор термина равен =:=
, а арность термина равна 2. Вы можете использовать write_canonical/1
, чтобы проверить это:
?- write_canonical(a =:= b).
=:=(a,b)
Предикат не является оператором
Все идет нормально! Все это было чисто синтаксической особенностью. Однако вы на самом деле спрашиваете о предикате (=:=)/2
, имя которого =:=
и который принимает 2 аргумента.
Как уже объяснили другие, предикат (=:=)/2
обозначает арифметическое равенство двух арифметических выражений. Оно истинно если его аргументы вычисляют одно и то же число.
Например, давайте попробуем самый общий запрос, с помощью которого мы запрашиваем какое-либо решение, используя переменные в качестве аргументов:
?- X =:= Y.
ERROR: Arguments are not sufficiently instantiated
Следовательно, этот предикат не является истинным отношением, поскольку мы не можем использовать его для генерирования результатов! Это довольно серьезный недостаток этого предиката, противоречащий тому, что вы обычно называете "декларативным программированием".
Предикат работает только в очень конкретной ситуации, когда оба аргумента полностью реализованы. Например:
?- 1 + 2 =:= 3.
true.
Мы называем такие предикаты режимными, потому что они могут использоваться только в определенных режимах использования. Для подавляющего большинства начинающих модерируемые предикаты являются кошмаром в использовании, потому что они требуют, чтобы вы думали о своих программах процедурно, что довольно сложно поначалу и остается трудным позже. Кроме того, модифицированные предикаты серьезно ограничивают универсальность ваших программ, потому что вы не можете использовать их во всех направлениях, в которых вы могли использовать чистые предикаты.
Ограничения являются более общей альтернативой
Пролог также предоставляет гораздо более общие арифметические предикаты в виде арифметических ограничений.
Например, в случае с целыми числами попробуйте ограничения CLP(FD) вашей системы Prolog. Одно из наиболее важных ограничений CLP(FD) обозначает арифметическое равенство и называется (#=)/2
. В полной аналогии с (=:=)/2
оператор (#=)/2
также определяется как инфиксный оператор, поэтому вы можете написать, например:
| ?- 1 + 2 #= 3.
yes
Я использую GNU Prolog в качестве одного из конкретных примеров, и многие другие системы Prolog также предоставляют реализации CLP(FD).
Основная привлекательность ограничений заключается в их общности. Например, в отличие от (=:=)/2
мы получаем с предикатом (#=)/2
:
| ?- X + 2 #= 3.
X = 1
| ?- 1 + Y #= 3.
Y = 2
И мы даже можем задать самый общий запрос:
| ?- X #= Y.
X = _#0(0..268435455)
Y = _#0(0..268435455)
Обратите внимание, как естественно эти предикаты сливаются с Прологом и действуют как отношения между целочисленными выражениями, которые можно запрашивать во всех направлениях.
В зависимости от интересующей области я рекомендую использовать CLP(FD), CLP(Q), CLP(B) и т. д. вместо использования более низкоуровневых арифметических предикатов.
См. также clpfd, clpq и clpb для получения дополнительной информации.
Так совпало, что оператор =:=
используется CLP(B) в совершенно другом значении:
?- sat(A =:= B+1).
A = 1,
sat(B=:=B).
Это показывает, что вы должны различать операторы и предикаты. В приведенном выше случае предикат sat/1
интерпретировал данное выражение как пропозициональную формулу, и в этом контексте =:=
обозначает равенство логических выражений.
person
mat
schedule
21.04.2017