Используйте арифметические операторы как конструкторы кортежей и пары минусов
Если вам нужно передать одну структуру, состоящую из двух или более значений, наиболее очевидная вещь - это список, например [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, она нам не нужна.