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

      Комментарии к записи Ответ в теме: Скалярное произведение векторов (списков) отключены
#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).

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