Я пытаюсь использовать Пролог foreach
в сжатой форме. Например, предположим, у меня есть список, и я хочу посмотреть, симметричен ли он. Рассмотрим следующий код:
isSymmetricList1(Size, List) :-
foreach(between(1, Size, I1), (
I2 is Size - I1 + 1,
nth1(I1, List, Elem),
nth1(I2, List, Elem)
)).
isSymmetricList2Sub1(Size, List, I1) :-
I2 is Size - I1 + 1,
nth1(I1, List, Elem),
nth1(I2, List, Elem).
isSymmetricList2(Size, List) :-
foreach(between(1, Size, I1), (
isSymmetricList2Sub1(Size, List, I1)
)).
Рассмотрим несколько тестовых случаев:
?- isSymmetricList1(4,[0,0,0,0]).
false.
?- isSymmetricList1(4,[0,0,0,1]).
false.
?- isSymmetricList1(4,[1,2,2,1]).
false.
?- isSymmetricList1(4,List).
false.
?- isSymmetricList2(4,[0,0,0,0]).
true.
?- isSymmetricList2(4,[0,0,0,1]).
false.
?- isSymmetricList2(4,[1,2,2,1]).
true.
isSymmetricList1
завершается ошибкой, возвращая только false
даже для симметричных списков. Я понимаю, почему это так, что I2
фактически входит в область действия isSymmetricList1
и поэтому может иметь только одно значение на всех 4 итерациях, что не соответствует его цели. В isSymmetricList2
я связываю I2
в isSymmetricList2Sub1
, вынимая его из области действия isSymmetricList2
, фактически позволяя привязать его к нескольким значениям (потому что это разные экземпляры или, как говорится).
Это работает. Тем не менее, это влечет за собой беспорядок. Я действительно не хочу, чтобы куча подправил плавала в моем пространстве имен. Я знаю, что есть лямбда-модуль , и, возможно, это просто то, что я должен использовать, но мне интересно знать, строго ли это необходимо. (Кроме того, его синтаксис немного сложен.) Можно ли использовать foreach
для выполнения действия более сложного, чем одна цель, без добавления дополнительных правил в пространство имен и без импорта дополнительных модулей? Например, если вы можете объявить локальные правила или ограничить область привязки.