Причина в том, что по умолчанию Пролог не интерпретирует +
, -
и другие арифметические операторы. 1+1
— это просто 1+1
(это синтаксический сахар для +(1,1)
), а не 2. Это может быть полезно, если вы, например, хотите определить свой собственный вычислитель выражений и видите +
как логическую сумму или что-то совершенно другое.
Однако существует один способ свернуть такое выражение, чтобы оно производило 2
из 1+1
, используя (is)/2
предикат. Например:
turn_to_east(NX,Y) :-
myPosition(X,Y),
NX is X+1,
write('East.').
Учитывая, что вы запрашиваете turn_to_east/2
с turn_to_east(1,2)
, NX = 1
. Теперь вы получаете данные myPosition/2
: X = 2
и Y = 2
. Тем временем Пролог выполняет проверку на эквивалентность и видит, что координата Y turn_to_east/2
такая же, как координата myPosition
. Затем он сворачивает 2+1
в 3
и видит, что это не эквивалентно NX = 1
, поэтому этот предикат не работает. Но если бы вы запросили turn_to_east(3,1)
, это было бы успешно, и поэтому напишите East.
.
Если вы измените всю свою теорию с помощью обсуждаемой выше концепции, например:
myPosition(2,2).
turn_to_east(NX,Y) :-
myPosition(X,Y),
NX is X+1,
write('East.').
turn_to_west(NX,Y) :-
myPosition(X,Y),
NX is X-1,
write('West.').
turn_to_north(X,NY) :-
myPosition(X,Y),
NY is Y+1,
write('North.').
turn_to_south(X,NY) :-
myPosition(X,Y),
NY is Y-1,
write('South.').
turn_to_the_point(X,Y) :- turn_to_east(X,Y).
turn_to_the_point(X,Y) :- turn_to_west(X,Y).
turn_to_the_point(X,Y) :- turn_to_north(X,Y).
turn_to_the_point(X,Y) :- turn_to_south(X,Y).
Он правильно отвечает на запрос:
?- turn_to_the_point(1,2).
West.
true ;
false.
В целом следует отметить, что предикаты лучше не иметь побочных эффектов, таких как write/1
: это не только для Пролога, почти все языки программирования советуют разделить программу на вычисление и взаимодействие. Возможно, лучший способ решить эту проблему - увидеть направление в качестве параметра:
myPosition(2,2).
turn_to_point(NX,Y,east) :-
myPosition(X,Y),
NX is X+1.
turn_to_point(NX,Y,west) :-
myPosition(X,Y),
NX is X-1.
turn_to_point(X,NY,north) :-
myPosition(X,Y),
NY is Y+1.
turn_to_point(X,NY,south) :-
myPosition(X,Y),
NY is Y-1.
turn_to_the_point(X,Y) :-
turn_to_point(X,Y,D),
write(D).
В этом случае предикат turn_to_the_point/2
явно является предикатом взаимодействия, тогда как его вариант turn_to_the_point/3
выполняет вычисления.
person
Willem Van Onsem
schedule
12.12.2015
turn_to_west(X-1,Y)
, например, не уменьшаетX
на 1. - person lurker   schedule 12.12.2015