Пролог арифметика в foreach - PullRequest
       0

Пролог арифметика в foreach

0 голосов
/ 27 сентября 2018

Итак, я изучаю пролог.Одна из вещей, которые я нашел действительно неприятными, продемонстрирована в следующем примере:

foreach(
  between(1,10,X),
  somePredicate(X,X+Y,Result)
).

Это не работает.Я хорошо знаю, что X + Y здесь не оценивается, и вместо этого я должен был бы сделать:

foreach(
  between(1,10,X),
  (
    XPlusY is X + Y,
    somePredicate(X, XPlusY, Result)
  )
).

Кроме того, это тоже не работает.Насколько я могу судить, область действия XPlusY выходит за пределы foreach, т. Е., XPlusY is 1 + Y, XPlusY is 2 + Y, и т. Д. Должны быть истинными сразу, и не существует XPlusY, для которого это имеет место.Поэтому я должен сделать следующее:

innerCode(X, Result) :-
  XPlusY is X + Y,
  somePredicate(X, XPlusY, Result).
...

foreach(
  between(1,10,X),
  innerCode(X, Result)
).

Это, наконец, работает.(По крайней мере, я так думаю. Я не пробовал этот точный код, но этот путь я выбрал ранее от «не работает» до «работает».) Это нормально и все, кроме того, что этоисключительно неприятный.Если бы у меня был способ вычисления арифметических операций в строке, я мог бы вдвое сократить строки кода, сделать его более читабельным и НЕ создавать одноразовый предикат беспорядка.

Вопрос: есть лиспособ оценить арифметические операции в строке, не объявляя новую переменную?

Если это не удастся, было бы приемлемо (и, в некоторых случаях, все еще полезно для других вещей), если бы был способограничить область применения новых переменных.Предположим, например, что вы можете определить блок в foreach, где были помечены видимые извне переменные, а любые другие переменные в блоке считались новыми для этого выполнения блока.(Я понимаю, что моя терминология может быть неправильной, но, надеюсь, она все поймет.) Например, что-то похожее:

foreach(
  between(1,10,X),
  (X, Result){
    XPlusY is X + Y,
    somePredicate(X, XPlusY, Result)
  }
).

Возможное решение может быть, если мы можем объявить лямбда-строку и немедленноназови это.Суммировано:

Альтернативный вопрос: есть ли способ ограничить область применения новых переменных в предикате, сохраняя при этом возможность выполнять длительные объединения для одной или нескольких существующих переменных?

(Вторую половину я добавил в качестве пояснения в ответ на ответ о forall.)

Решение обоих вопросов предпочтительнее, но решения любого из них будет достаточно.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018
Библиотека

( yall ) позволяет определять лямбда-выражения.Например,

?- foreach(between(1,3,X),call([Y]>>(Z is Y+1,writeln(Z)),X)).
2
3
4
true.

В качестве альтернативы библиотека ( lambda ) предоставляет конструкцию:

?- [library(lambda)].
true.

?- foreach(between(1,3,X),call(\Y^(Z is Y+1,writeln(Z)),X)).
2
3
4
true.

В SWI-Prolog библиотека (yall) автоматически загружается, а дляполучить библиотеку (лямбда) вы должны установить соответствующий пакет:

?- pack_install(lambda).
0 голосов
/ 27 сентября 2018

В качестве альтернативы используйте стандартный предикат forall/2 de facto:

forall(
  between(1,10,X),
  somePredicate(X,X+Y,Result)
).

В то время как предикат foreach/2 обычно реализуется описанным вами способом, предикат forall/2 определяется как:

% forall(@callable, @callable)

forall(Generate, Test) :-
    \+ (Generate, \+ Test).

Обратите внимание, что использование отрицания подразумевает, что при успешном вызове предиката привязки возвращаться не будут.

Обновление

Лямбда-библиотеки позволяютспецификация как лямбда-глобальных (иначе лямбда-свободных), так и лямбда-локальных переменных (или лямбда-параметров).Используя синтаксис Logtalk lambdas (доступен также в SWI-Prolog в library(yall), вы можете написать (повторно используя пример Карло), например,

?- G = 2, foreach(between(1,3,X),call({G}/[Y]>>(Z is Y+G,writeln(Z)),X)).
3
4
5
G = 2.

?- G = 4, foreach(between(1,3,X),call({G}/[Y]>>(Z is Y+G,writeln(Z)),X)).
5
6
7
G = 4.

Таким образом, можно использовать лямбда-выражения для ограничения области действия некоторых переменных в пределахцель, не ограничивая при этом сферу каждого объединения в цели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...