Вот решение, в котором вам все еще нужно написать немного кода для каждого оператора, который вы хотите обработать, но который по-прежнему обеспечивает хороший синтаксис в момент использования.
Давайте начнем с понятия вычисления арифметического выражения на векторах для вектора. Это по существу применяет арифметические операции компонентно. (Но вы можете добавить точечный продукт или что угодно.)
:- use_module(library(clpr)).
vectorexpr_value((X,Y,Z), (X,Y,Z)).
vectorexpr_value(V * T, (X,Y,Z)) :-
vectorexpr_value(V, (XV,YV,ZV)),
{ X = XV * T },
{ Y = YV * T },
{ Z = ZV * T }.
vectorexpr_value(L + R, (X,Y,Z)) :-
vectorexpr_value(L, (XL,YL,ZL)),
vectorexpr_value(R, (XR,YR,ZR)),
{ X = XL + XR },
{ Y = YL + YR },
{ Z = ZL + ZR }.
vectorexpr_value(L - R, (X,Y,Z)) :-
vectorexpr_value(L, (XL,YL,ZL)),
vectorexpr_value(R, (XR,YR,ZR)),
{ X = XL - XR },
{ Y = YL - YR },
{ Z = ZL - ZR }.
Так, например:
?- vectorexpr_value(A + B, Result).
A = (_1784, _1790, _1792),
B = (_1808, _1814, _1816),
Result = (_1832, _1838, _1840),
{_1808=_1832-_1784},
{_1814=_1838-_1790},
{_1816=_1840-_1792} .
Учитывая это, теперь мы можем определить «равенство» векторных выражений, «оценив» их оба и заявив точечное равенство результатов. Чтобы это выглядело хорошо, мы можем определить для него оператор:
:- op(700, xfx, ===).
Это определяет ===
как инфиксный оператор с тем же приоритетом, что и у других операторов равенства =
, =:=
и т. Д. Prolog не позволяет перегрузить операторы, поэтому мы создали новый. Вы можете думать о трех =
знаках в операторе как о выражении равенства в трех измерениях.
Вот соответствующее определение предиката:
ExprL === ExprR :-
vectorexpr_value(ExprL, (XL,YL,ZL)),
vectorexpr_value(ExprR, (XR,YR,ZR)),
{ XL = XR },
{ YL = YR },
{ ZL = ZR }.
И теперь мы можем определить line/4
почти так, как вы хотели:
line(P1, P2, T, P3) :-
(P2 - P1) * T === P3.
Тесты:
?- line((0,0,0), (1,1,1), Alpha, (2,2,2)).
Alpha = 2.0 ;
false.
?- line((0,0,0), (1,1,1), Alpha, (2,3,4)).
false.