Пролог Поля суммирования в базе данных - PullRequest
1 голос
/ 20 марта 2012

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

Sample database:

tastiness(bacon,100,200,300,400,500).
tastiness(lettuce,3,5,6,7,12).

Sample output
(bacon,1500).
(lettuce,33).

Ответы [ 2 ]

1 голос
/ 21 марта 2012

В качестве примечания, вычисление суммы, предложенное @aioobe, не является оптимальным, потому что в очень большом списке вам не хватит памяти стека вызовов.

Особая техника - поместить рекурсивный вызов предиката в качестве последнего элемента вашего предиката. Таким образом, когда все предыдущие вещи уже вычислены, Prolog может сбросить текущий контекст предиката при выполнении рекурсивного вызова. В списке с элементами 1M это означает, что вы будете работать с сохранением 1 контекста вместо одного миллиона.

Хотя это может показаться вам неважным для этого конкретного упражнения, оптимизация хвостового вызова - это то, что делает рекурсию такой же мощной, как итерация, если принять во внимание потребление пространства. Это стоит учиться!

Вот версия, на которой Оптимизация Tail Call может выполняться:

sumlist(List, Result) :-
    sumlist(List, 0, Result).

sumlist([], Acc, Acc).
sumlist([Item|List], Acc, Result) :-
    NewAcc is Acc + Item.
    sumlist(List, NewAcc, Result).

В нем используется идиома, которую вы часто встречаете в декларативном программировании: аккумулятор (здесь он называется Acc). Его цель - сохранить полученное значение «до сих пор» во время рекурсии.

1 голос
/ 20 марта 2012

Вот как суммировать значения списка в стандартном прологе:

sumlist([], 0).
sumlist([X|Xs], Sum) :-
    sumlist(Xs, SumTail),
    Sum is X + SumTail.

Если у вас есть что-то вроде

bacon(100).
bacon(200).
bacon(300).
bacon(400).
bacon(500).

, вы можете использовать findall предикат.Предикат findall работает следующим образом: Если вы хотите Z = [100, 200, 300, 400, 500] (список всех чисел бекона), вы пишете findall(X, bacon(X), Z).

Вот как суммировать все числа бекона:

| ?- findall(X, bacon(X), AllBacon), sumlist(AllBacon, SumBacon).

AllBacon = [100,200,300,400,500]
SumBacon = 1500

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