Одиночные переменные в прологе
Я тестировал свою новую версию пролога SWI и продолжаю сталкиваться с ошибкой: singleton variable.
Пример:
member(X,[X|T]).
member(X,[X|T]) :- member(X,T).
находит элемент списка, например:
member(yolands,[yolanda,tim])
X = yes
но вместо этого я получаю ошибку singleton variables для X и T
если я делаю следующее:
member(X,[X|_]).
member(X,[_|T]) :- member(X,T).
Это работает, но выглядит уродливо!
Может ли кто-нибудь объяснить, почему разрешены одиночные переменные и если этот стандарт ANSI?
Ответы
Ответ 1
Синглтонные переменные бесполезны в Prolog и легко вводятся путем редактирования опечаток.
Предупреждение приветствуется для меня, поскольку оно позволяет легко выявить такую частую причину ошибки.
Будучи предупреждением, вы можете запускать код, содержащий одиночные числа, но любое значение, которое они в конечном итоге предполагают, будет потеряно.
Я не думаю, что стандарт ISO (никогда не слышал об ANSI) запрещает такие переменные.
Вы можете переписать свой пример таким образом
member(X, [Y|T]) :- X = Y ; member(X, T).
а затем забудьте о синглете.
Ответ 2
У вас есть ошибка здесь:
member(X,[X|T]) :- member(X,T).
То, что вы на самом деле говорит (в отличие от того, что, по вашему мнению, вы говорите), заключается в том, что member/2
выполняется, если X находится во главе списка и присутствует в хвосте списка. Этот предикат будет только когда-либо истинным для первых N копий одной и той же вещи в начале списка, поэтому очень странно сказать!
?- member(X, [a,a,c]).
X = a ;
X = a ;
false.
?- member(X, [b,a,a]).
X = b ;
false.
Теперь вы можете исправить ошибку и по-прежнему иметь одноэлементное предупреждение, выполнив что-то вроде этого:
member(X, [Y|T]) :- member(X, T).
Но это не так хорошо, как обычное определение с двумя головами или версия @CapelliC (+1) с явным OR. Я думаю, вам стоит подождать, пока вы не поймете Prolog немного лучше, прежде чем вкладывать много акций в ваш смысл эстетики кода Prolog. Если вы будете придерживаться этого какое-то время, вы поймете это предупреждение, а также использование анонимных переменных.
То, что делает одиночные переменные бесполезными в Prolog, состоит в том, что они названы, но о них ничего не известно, и они не влияют на остальную часть вычислений. Подчеркивание подчеркивает, что абсолютно все может идти туда, не затрагивая смысла. Что делает
member(X, [X|T]).
true заключается в том, что X является позицией 1 такой же, как X в начале списка в позиции 2. Списки должны быть пустыми или иметь голову и хвост, но то, что в хвосте здесь не имеет значения, важно то, что Х - тоже голова. T может быть остальной частью списка, или это может быть неправильный список, или это может быть хлеб или молния или запах воздуха в день spring. Он не имеет никакого отношения к истине member(X, [X|T])
.
Предупреждение singleton сообщает вам: "Вы зарезервировали имя для чего-то здесь, но вы никогда не называете что-либо под этим именем". Первое, что я делаю, когда получаю это сообщение, и это не очевидная опечатка, заменит имя на _ и посмотрим, действительно ли мой код имеет смысл. Если это не так, у меня есть логическая ошибка. Если это так, это, вероятно, не нужно.
Ответ 3
Вы можете прочитать об этом на официальной странице FAQ SWI-Prolog
Наиболее распространенными случаями этого предупреждения являются:
- Ошибки орфографии в переменных
- Забудьте использовать/привязать переменную
SWI предлагает несколько способов игнорировать его:
- Для этой цели используйте анонимную переменную с именем _.
- Используйте переменную, начинающуюся с _ (например,
_T
, _X
), чтобы избежать предупреждения и документировать то, что вы игнорируете.
- Если вы знаете, что делаете, вы можете использовать
:- style_check(-singleton).
, и все предупреждения должны исчезнуть.