2017-01-11 6 views
0

결과를 어떻게`fresh` 변경 설명 core.logic : (1 1) :그냥 버전 "0.8.11"<a href="https://github.com/clojure/core.logic" rel="nofollow noreferrer">core.logic</a> 함께 시작

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

가 나는 결과를 이해하지 않습니다. , (1), 또는 (1 2 1 3) :

나의 이해는 내가 그러므로 내가 좋아하는 무언가를보고 기대 한 1의 값을 취할 수 2 또는 3 그리고 q의 값을 취할 수 신선한 또 다른 변수 a을 만들 것입니다 ([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은 충돌을 일으키지 않는 모든 관련 변수에 값을 할당하는 가능한 방법을 검색하여 검색 알고리즘을 볼 수 있습니다. 그것은 매우 똑똑한 가지 치기 기술을 많이 가지고 있으므로 좋지 않은 것으로 알려진 하위 트리를 검색하지는 않지만 기본적으로는 검색입니다.

  • A = 2, Q = 1
  • A = 3, q는 = 1

그래서 두 개의을 반환 :

그것은 쿼리를 만족 변수를 지정하는 두 가지 방법을 발견 결과. 그러나 질문에 대해서만 물어보십시오. (그게 run*의 인수입니다. 값을 알고 싶은 변수의 집합입니다.) 그리고 q는 두 할당에서 동일합니다. 따라서 같은 결과 (1)가 두 번 보입니다. 일반적인 시도가 아닌 한 run*의 결과가 별개라고 가정하지 말아야합니다.

마지막 예제에서 q에 할당 할 수있는 값은 세 가지가 있으며 각 값은 a에 할당 할 수있는 세 가지 값에 대해 작동하므로 각 q와 함께 3 * 3 = 9 개의 결과를 얻습니다. 값은 세 번 반복됩니다. 이러한 결과가 반환되는 순서는 (사용자의 관점에서) 임의적입니다. 실제로 그들은 core.logic이 다른 복잡한 프로그램에서 교착 상태를 방지하는 데 도움이되는 방식으로 정렬됩니다. 원하는 경우 모든 a, q 쌍을 볼 수 있습니다. 대신 (q/run* [a q] ...)을 작성하십시오.