Пролог: суммировать элементы списка - PullRequest
0 голосов
/ 03 июля 2018

Я очень новичок в прологе и пытаюсь суммировать элементы списка. Пока у меня есть это:

     sum([],_,_). %base case
     sum([H|T], Y, _X):-
        X2 is H + Y,
        sum(T,X2,X2).

тестирование с суммой ([1,2,3,4], 0, X) приводит к ошибке, но я не уверен, что не так с этим кодом. Может ли кто-нибудь указать мне правильное направление?

1 Ответ

0 голосов
/ 03 июля 2018

Код, который вы дали, ближе к работе, чем вы, возможно, думаете, но у него есть пара проблем.

Во-первых, предикаты Prolog не являются функциями, они не возвращают результаты, как функции в других языках. Предикаты вместо этого заявляют что-то о том, что является правдой. Позже вы можете задавать пролог-запросы, и он попытается их реализовать.

Например, вызовы length / 2 имеют значение true, когда левый аргумент представляет собой список, а правый аргумент представляет собой int с длиной списка:

?- length([1, 2, 3, 4], 4).
true.

?- length([1, 2, 3, 4], X).
X = 4.

?- length(X, 2).
X = [_2300, _2306].

Оглядываясь на первую строку:

sum([],_,_). %base case

Здесь написано, что "sum / 3 всегда верно, если первый элемент является пустым списком". Вы можете проверить это:

?- sum([], -20, hello).
true.

Это, вероятно, не то, что вы намеревались.

Я не уверен, как сложить все остальное, не выдав ответ, но посмотрите, что говорится в этом пункте:

 sum([H|T], Y, _X):-
    X2 is H + Y,
    sum(T,X2,X2).

«sum([H|T], Y, WhoCaresIllNeverUseThisVariable) верно, если мы можем повторить и доказать, что sum(T, H+Y, H+Y) верно».

Хорошо, последний аргумент немного странный, потому что в обоих пунктах вы присваиваете его анонимной переменной (_ и _X). То, что вы говорите, «третий аргумент никогда не имеет значения и должен соответствовать буквально всему, что бросает в него использование». Я не думаю, что вы это хотели сказать.

Второй момент, я не знаю, понимаете ли вы это, но вы фактически вычисляете здесь сумму! При попытке сделать sum([1, 2, 3, 4], 0, X) true Пролог будет проходить по списку и добавлять каждый элемент к среднему аргументу, вашему аккумулятору. Суммирующая часть работает! То, что вы не можете сделать, это извлечь сумму из этого предиката.

Обычно в Прологе вы «возвращаете» результаты, выдавая им дополнительный аргумент. Вы можете посмотреть на длину / 2 таким образом. Вот способ, которым вы могли бы написать это самостоятельно:

my_length([], 0).
my_length([_|Rest], Length) :-
  my_length(Rest, Length1),
  Length is Length1 + 1.

Эта функция «возвращает» длину массива, будучи истинной, только когда второй аргумент предиката является длиной массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...