2017-01-21 9 views
1

Я написал программу для сортировки чисел из символов, и она работает, но дает мне адрес памяти в конце списка, который он не пропустил последним. Почему это так?Необязательная переменная в конце списка в SWI-Prolog

separate([],[],[]). 
separate([X],X,_):-number(X). 
separate([X],_,X). 
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S). 
separate([X|Y],Z,[X|S]):-separate(Y,Z,S). 

При консультации с ?- separate([3,a,b,4,5,c],X,Y).

я получаю:

X = [3, 4, 5|_G2592], 
Y = [a, b, c] . 
+0

Вместо нажатия «Enter» после просмотра ответа, что произойдет, если вы нажмете пробел. См.: [Почему SWI-Prolog дает мне первый ответ?] (Http://stackoverflow.com/q/34463248/1243762) –

+0

Это также помогает при первом обучении Prolog не использовать переменные типа 'X' и' Y 'но более значимые имена, такие как' Digit', 'Letter',' Digits', 'Letters',' Rest'. Как только вы поймете, что происходит, вы можете вернуться к «X» и «Y» и т. Д. –

ответ

1

Это потому, что вы оставить список ваших хвосты открытым:

 
separate([X],X,_):-number(X). 
separate([X],_,X). 

Дело в том, вы на самом деле не нужно писать эти заявления, вы могли бы опустить их:

separate([],[],[]). 
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S). 
separate([X|Y],Z,[X|S]):-separate(Y,Z,S). 

Этот работал бы , но он возвратил бы несколько результатов и кроме первого, все остальные ошибочны. Вы должны решить эту проблему, добавив охранника последнего пункта:

 
separate([],[],[]). 
separate([X|Y],[X|Z],S):-number(X),separate(Y,Z,S). 
separate([X|Y],Z,[X|S]):-\+ number(X),separate(Y,Z,S). 

Где \+ действует как «не» в том смысле, что \+ number(X) будет успешным, если Пролог может не совпадать number(X).

Заключительное примечание состоит в том, что то, что вы видите, на самом деле не является адресом памяти: это просто необозначенная переменная, хотя это, конечно, незначительное замечание.

+0

Не был уверен, что это адрес памяти или нет, но это был самый близкий, я думал, это было, спасибо, что очистили это слишком. The \ + неизвестен мне и никогда не упоминался в нашем скрипте. – Streamline

+0

@Streamline: ah '\ +' действует как «не» (хотя это опасно говорить). Это не в том смысле, что если Prolog не соответствует 'number (a)', например, '\ + number (a)' будет успешным. –

2

Я предлагаю

separate([],[],[]). 

separate([H | T], [H | Tn], Ls) :- 
    number(H), 
    separate(T, Tn, Ls). 

separate([H | T], Ln, [H | Ts]) :- 
    \+ number(H), 
    separate(T, Ln, Ts). 

Если у вас есть терминальное положение как separate([],[],[]) и несколько простых пунктов, как separate([X|Y],[X|Z],S) и separate([X|Y],Z,[X|S]), вам не нужен полутерьер minal clauses как separate([X],X,_) и separate([X],_,X), и они (с неопределенным значением _) избегают объединения одного из списков, и вы получаете «адрес памяти» (идентификатор не унифицированной переменной).

И если у вас есть пункт с number(X), другой (альтернативный) пункт нуждается в «не-число» чек (то есть \+ number(X)) в противном случае оба положения верны с числами и умножении решения, с номерами в списке а не числа.