В контексте nafc
входы без заземления обрабатываются путем предоставления выходов без заземления, поэтому для получения значимых ответов ваши входы "должны быть заземлены". Он не может отменить ограничение, включающее неосновные значения.
Например, эта программа выдает все возможные значения q
, где q
удовлетворяет emptyo
:
(run* [q]
(emptyo q))
;=> (())
Если мы запрашивая все возможные значения q
, которые не удовлетворяют emptyo
, мы получаем это:
(run* [q]
(nafc emptyo q))
;=> ((_0 :- (clojure.core.logic/nafc #object[clojure.core.logic$emptyo 0x212442c1 "clojure.core.logic$emptyo@212442c1"] _0)))
Упрощенная формулировка - ((_0 :- (nafc emptyo _0)))
, что означает, что есть только один ответ, но это может быть любое значение, удовлетворяющее ограничению RHS. Программа logi c не может дать нам базовые значения, потому что она не знает всех возможных непустых списков.
Вот пример настройки БД для полноты:
(pldb/db-rel page q)
(pldb/db-rel link p q)
(def facts
(pldb/db
[page 'a]
[page 'b]
[page 'z]
[link 'a 'b]
[link 'b 'c]))
И ваша рабочая программа с битыми ссылками:
;; find links to non-pages
(pldb/with-db facts
(run* [p q]
(link p q)
(nafc page q)))
;=> ([b c])
Вот способ написать потерянную страницу программы:
;; find pages without incoming links
(pldb/with-db facts
(run* [q]
(fresh [p]
(page q)
(conda
[(link p q) fail]
[succeed]))))
;=> (a z)
Отрицание здесь выражается с помощью conda
, чтобы сформировать вид if-else logi c: если есть ссылка на страницу q
we fail
else we succeed
.
Также обратите внимание на использование fresh
, чтобы ввести переменную logi c p
, которая не является частью желаемого вывода ответа, так как мы заботимся только о потерянных значениях страницы.