Проблема в том, что
multiply(A,B,C) :- D is B-1, multiply(A,D,E), C is E+A.
Этот код не имеет ограничения B > 0
, которое могло бы предотвратить переполнение стека.
Вы можете изменить код следующим образом:
multiply(A,B,C) :- B > 0, D is B-1, multiply(A,D,E), C is E+A.
Кроме того, эта строка multiply(A,0,0).
выдает одноэлементное предупреждение, поэтому вы можете изменить его на multiply(_,0,0)
Примечание : я написал ограничение B > 0
, полагая, что вы называете предикат multiply(5,1,A)
.
Я лично говорю «расширяет», и я подумал , что спецификация C # также где-то использует это слово (я не могу его найти сейчас, к сожалению) - но я помню Эрика Липперт сказал, что он не заинтересован в этом, и хотел изменить его на 4.0.
Я думаю, что это хорошо, потому что это показывает, что вы продлеваете контракт, указанный в исходном интерфейсе.
РЕДАКТИРОВАТЬ: Посмотрев на спецификация 3.0 ...
Спецификация как бы обходит проблему в разделе 13.2. Это говорит о членах, унаследованных от базовых интерфейсов. Он говорит о том, что один класс расширяет другой, но не интерфейсы
. РЕДАКТИРОВАТЬ: В спецификации C # 5, раздел 13.1.4, он использует наследует:
Интерфейс может наследовать от нуля или более типов интерфейса.
Так что это, вероятно, лучший термин для использования.
вы ошиблись в определении.
B: A означает «B наследует от A».
когда мы говорим «B реализует InterfaceA», это обычно означает, что InterfaceA не есть определение для функционирования - это только прототипы (или PURE в C ++). Однако в C ++ и большинстве OOPL наследование и реализация имеют одинаковый синтаксис.
Таким образом, InterfaceB: InterfaceA по-прежнему означает «InterfaceB наследует InterfaceA».
Почему было бы неправильно говорить, что InterfaceB «наследует» или «происходит от» InterfaceA? «Реализует» было бы неправильно, потому что InterfaceB не обеспечивает реализацию. Семантически, производные интерфейсы очень похожи на производные классы. C ++, например, вообще не различает интерфейсы и классы.