Используйте арифметические операторы как конструкторы кортежей и пары минусов
Если вам нужно передать одну структуру, состоящую из двух или более значений, наиболее очевидная вещь - это список, например [A,B] . Это действительно многословно, хотя.
Есть альтернатива. Значения Пролога могут хранить в значительной степени произвольную вложенную структуру, которая не оценивается. Вот пример, показывающий, как это работает:
| ?- member(member(A,B),C).
C = [member(A,B)|_] ? ;
C = [_,member(A,B)|_] ? ;
(etc.)
member(A,B) это просто именной кортеж в этой ситуации, а снаружи member объект (который является вызовом функции) рассматривает его как таковой.
Хотя именованные кортежи довольно полезны в прологическом программировании без игры в гольф, они могут показаться даже более многословными, чем подход списка. Тем не менее, мы можем использовать произвольные символы в имени конструктора кортежей (при условии, что они правильно указаны в кавычках); вместо чего-то милого memberили единственного символа aмы можем сделать что-то вроде этого:
| ?- A = '-'('/'(1,2), '/'(3,4)).
A = 1/2-3/4
Здесь наши конструкторы кортежей '-'и '/'. И интересно отметить, что симпатичный принтер сделал с ними; он использует инфиксную нотацию для кортежей. Это действительно кратко и анализирует так же, как и сравнимая арифметическая операция. (Это также объясняет, почему арифметика isне использует =; A = 1+2будет объединяться Aс кортежем '+'(1,2) , поэтому для фактической оценки неоцененного арифметического выражения необходим отдельный синтаксис.) Поскольку конструктор кортежа должен вызываться как- то , вы также можете использовать символ с кратким синтаксис (и в качестве бонуса, -и/ это одни из самых распространенных вариантов в неигровом коде также, когда им нужен быстрый одноразовый конструктор кортежей, а не что-то значимое, почти так же, какi часто используется как переменная цикла, поэтому их вполне целесообразно использовать при вводе и выводе, если по какой-то причине вам нужен кортеж).
'-'и '/'являются хорошим выбором для конструкторов кортежей, потому что они хорошо себя ведут и имеют полезный приоритет, что позволяет вам кратко писать литералы кортежей. Однако обратите внимание, что вам не нужно беспокоиться о приоритете, когда промежуточные значения создаются внутри программы. Prolog хранит кортежи в виде дерева, а не исходного кода, и симпатичные принтеры могут выводить его однозначно:
| ?- A = '-'('-'(1,2), '-'(3,4)).
A = 1-2-(3-4)
Потому что синтаксис кортежа очень краткий ( f(A,B)не корочеf(A-B) ), вы можете бесплатно заменить несколько аргументов предиката на кортежи, что означает, что если предикату нужно передать два или более своих аргументов другому предикату, вы часто можете сформировать их в кортеж и просто передайте кортеж (хотя для этого потребуется изменить все вызовы предиката, в дополнение к самому предикату, чтобы использовать соответствующее сочетание конструкторов кортежа и запятых).
Еще одним преимуществом этого синтаксиса является необходимость использования списков для внутреннего использования (а не для взаимодействия со стандартными предикатами); список - это просто набор вложенных cons-ячеек, а cons-ячейка - это просто кортеж с конструктором '.', как можно увидеть здесь:
| ?- Q = '.'('.'(A,B),'.'(C,D)).
Q = [[A|B],C|D]
Если ваш код использует списки «вручную», имеет смысл использовать менее громоздкий конструктор кортежей, чем '.'. Обычный выбор для меня состоит в том, чтобы представлять ячейку cons как '/'(Tail,Head)(потому что она является наиболее читаемой, которую вы можете получить в отладочном выводе без потери символов). Обратите внимание, что вы, вероятно, []тоже захотите свой собственный эквивалент; вы могли бы использовать[] но это два байта длиной, и есть много однобайтовых атомов (все строчные буквы), которые вы можете использовать вместо этого.
Так, например, следующий список:
[1,2,3]
может быть преобразовано в ручное представление в том же количестве символов, как это:
x/3/2/1
в то же время, получая преимущество, что [H|T]сопоставление с шаблоном-стиля теперь может быть записано более кратко как T/Hи проверка пустого списка как более точного , xчем более длинного []. (Конечно, это приходит с очевидным недостатком , что member, appendи т.д., не будет работать на этом представлении.)
prologТег любопытное бесполезно. Если у нас нет задачи Interpret Prolog, она нам не нужна.