Пролог умножить все элементы списка

Я хочу определить предикат в Prolog, prod_list/2, который умножает каждый элемент списка. У меня проблема с пустым списком, желаю, чтобы продукт был нулевым, вместо этого я получаю false. Мой код

prod_list([H], H).
prod_list([H|T], Product) :- prod_list(T, Rest), 
                            Product is H * Rest.

Я получаю результаты prod_list([4,3],Product). -> Product = 12, но когда я делаю prod_list([], Product). Я получаю false вместо Product = 0.

Пожалуйста помоги.

2 ответа

Решение

Ваша проблема в том, что ни одно предложение не соответствует пустому списку. На самом деле у вас есть рекурсивное предложение:

prod_list([H|T], Product) :- prod_list(T, Rest), 
                        Product is H * Rest.

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

prod_list([H], H).

Итак, ни в коем случае не пустой список [] соответствует предложению, и по этой причине ответ false (нет совпадений).

Чтобы решить вашу проблему, вам нужно включить явное предложение для пустого списка:

prod_list([],0).
prod_list([H],H).
prod_list([H|T], Product) :- prod_list(T, Rest), Product is H * Rest.

Можно найти другое решение, учитывая, что произведение пустого списка должно быть (правильно) определено следующим образом:

product_of_list([], 1).
product_of_list([H|T], Product) :- product_of_list(T, Rest), Product is H * Rest

тогда вы можете добавить свое "специальное" определение prod_list:

prod_list([],0).
prod_list(List, Product) :- product_of_list(List, Product).

редактировать

Последнее решение не работает для некоторых интерактивных версий Prolog (например, Swish on-line), в то время как оно работает для SWI-Prolog (многопоточный, 64-битный, версия 7.3.11). Решения, которые должны работать для каждой версии, следующие:

prod_list([],0).
prod_list([H|T], Product) :- product_of_list([H|T], Product).

Спасибо user474491 за обнаружение этого.

Ответ Ренцо идеален. Я просто подумал о функциональной обработке списков, когда увидел твой вопрос. Вы можете получить их на тот случай, если они вам понадобятся. Если вы определите умножение функции:

mul(V1,V2,R) :- R is V1*V2;

тогда вы можете использовать foldl в любом из его вариантов:

?- foldl(mul, [1,2,10], 1, R).
R = 20 .

fold является традиционной функциональной функцией вычисления, которая применяет функцию, накапливающую временный результат.

Другие вопросы по тегам