2017-01-11 5 views
0

Только начиная с core.logic, версия "0.8.11":core.logic объяснить, как `fresh` изменения результатов

(q/run* [q] 
    (q/fresh [a] 
     (q/membero a [2 3])) 
    (q/membero q [1])) 

Я не понимаю, результат: (1 1).

Я понимаю, что я создаю еще одну переменную a с свежей, которая может принимать значение 2 или 3. И q может принимать значение 1. Поэтому я ожидал увидеть что-то вроде: (1) или (1 2 1 3), или, может быть, ([1 2] [1 3]) или даже ({:q 1 :a 2} {:q 1 :a 3}), но не фактический результат.

Другой пример:

(q/run* [q] 
    (q/fresh [a] 
     (q/membero a [1 2 3]) 
     (q/membero q [3 4 5]) 
     (q/== a q))) 
    ;; make sense to me, returns (3) 

    (q/run* [q] 
    (q/fresh [a] 
     (q/membero a [1 2 3])) 
    (q/membero q [3 4 5])) 
    ;; does not make sense to me, returns (3 4 3 5 4 3 5 4 5) 
    ;; I was expecting `(3 4 5)` 

Может кто-нибудь объяснить, что здесь происходит?

ответ

4

core.logic можно просмотреть алгоритм поиска, в котором можно найти возможные способы присвоения значений всем соответствующим переменным, которые не вызывают конфликта. У этого есть много очень умных методов обрезки, чтобы он не искал поддеревья, которые, как известно, не являются хорошими, но в основном это поиск.

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

  • а = 2, д = 1
  • а = 3, д = 1

Так что возвращающегося два Результаты. Но вы только спрашиваете о q (вот что аргумент run* - это набор переменных, которые вы хотите знать значениями), а q одинаково в обоих этих назначениях, поэтому вы видите один и тот же результат (1) дважды. Вы не должны вообще предполагать, что результаты от run* будут отличаться, если только вы не приложили усилий, чтобы сделать их такими.

Аналогичным образом в вашем последнем примере есть три значения, которые вы можете назначить q, и каждый из них работает для любого из трех значений, которые вы могли бы присвоить a, поэтому вы получаете 3 * 3 = 9 результатов, причем каждый q значение повторяется три раза. Порядок, в котором эти результаты возвращаются, является (с вашей точки зрения) произвольным; на самом деле они упорядочены таким образом, что помогает core.logic предотвращать блокировку в других, более сложных программах. Вы могли видеть все пары a, q, если хотите, написав вместо этого (q/run* [a q] ...).