Ответ в теме: Скалярное произведение векторов (списков)

      Комментарии к записи Ответ в теме: Скалярное произведение векторов (списков) отключены
#2049

Если оба вектора пусты – то произведение равно нулю. В противном случае от список отделяются первый элементы, а хвосты – обрабатываются рекурсивно. К результату, полученному при обработке хвостов добавляется выражение HeadA*HeadB.

scalar_multiplication([], [], 0):-!.
scalar_multiplication([HeadA|TailA], [HeadB|TailB], Multiplication):-
  scalar_multiplication(TailA, TailB, TailMultiplication),
  Multiplication is TailMultiplication + HeadA * HeadB.

Это простой вариант, однако он не очень эффективный – лучше использовать хвостовую рекурсию. При хвостовой рекурсии вызов функции идет последним, поэтому может быть заменен безусловным переходом (фактически циклом). Для оптимизации функции используется метод накапливающего параметра – результат накапливается в одном из аргументов функции. Начальное значение суммы, равное нулю, должно передаваться в качестве накопителя при первом вызове – сделать это можно во вспомогательной функции:

scalar_multiplication(ListA, ListB, Multiplication):-
  scalar_multiplication(ListA, ListB, 0, Multiplication).
  
scalar_multiplication([], [], Multiplication, Multiplication):-!.
scalar_multiplication([HeadA|TailA], [HeadB|TailB], Buffer, Multiplication):-
  NewBuffer is Buffer + HeadA * HeadB,
  scalar_multiplication(TailA, TailB, NewBuffer, Multiplication).

На каждой итерации функции вычисляет новое значение буфера-накопителя (частичный результат) и передает его для рекурсивной обработки. Когда оба вектора закончились – накопленный результат переписывается в выходной буфер.