Ошибка при определении длины в SWI Prolog - PullRequest
0 голосов
/ 27 июня 2018

Я определил процедуру с именем length в файле с именем test.pl:

% Finds the length of a list.
length([], 0).
length([_ | Tail], N) :-
    length(Tail, N1),
    N is 1 + N1.

Когда программа запускается с использованием SWI-Prolog (prolog test.pl), появляется следующая ошибка:

ERROR: /home/user/test.pl:2:
    No permission to modify static procedure `length/2'
    Defined at /usr/lib/swi-prolog/boot/init.pl:3496
ERROR: /home/user/test.pl:3:
    No permission to modify static procedure `length/2'
    Defined at /usr/lib/swi-prolog/boot/init.pl:3496

Я попытался изменить имя процедуры с length на mylength, и ошибка исчезла. Что означает эта ошибка? Могу ли я определить процедуру с именем length? Если нет, то почему это не может быть сделано?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

length / 2 не определен в Прологе, но вместо этого он является частью поверхностного интерфейса над собственной (высокоэффективной) реализацией списков. Вы должны использовать директиву redefine_system_predicate .

Например, сохранить в файле redef_length.pl

:- redefine_system_predicate(length(?,?)).

% Finds the length of a list.
length([], 0).
length([_ | Tail], N) :-
    length(Tail, N1),
    N is 1 + N1.

тогда проконсультируйтесь

?- [test/prolog/redef_length].
true.

?- trace.
true.

[trace]  ?- length(A,B).
   Call: (8) length(_1476, _1478) ? creep
   Exit: (8) length([], 0) ? creep
A = [],
B = 0 ;
   Redo: (8) length(_1476, _1478) ? creep
   Call: (9) length(_1718, _1738) ? creep
   Exit: (9) length([], 0) ? creep
   Call: (9) _1478 is 1+0 ? creep
   Exit: (9) 1 is 1+0 ? creep
   Exit: (8) length([_1716], 1) ? creep
A = [_1716],
B = 1 
0 голосов
/ 27 июня 2018

Это верно. length/2 - это встроенный предикат : длина (? List,? Int) - True, если Int представляет количество элементов в List . Так что имя уже используется.

...