2014-01-29 20 views
2

我在用core.logic玩弄周圍,並嘗試翻譯一些Prolog代碼並運行到insert事實的無盡的遞歸(摘自RAO'Keefe的「Prolog of Prolog 「):將插入的事實從Prolog轉換爲core.logic

insert(L, X, [X|L]). 
insert([H|T], X, [H|L]) :- 
     insert(T,X,L). 

這是我想出迄今(請注意,前兩個參數是交換與conso參數列表匹配):

(defn insert [x l nl] 
    (conde 
     [(conso x l nl)] 
     [(fresh [h t] 
     (conso h t l) 
     (insert x t l) 
     (conso h l nl))])) 

我的問題是從這些midje測試的最後兩個事實將永遠不會r E打開。 第一個工作正常,因爲這隻需要第一個conso條款。

(fact "Inserting works" 
     (run* [q] (insert 1 [2] q)) => '((1 2))) 
     (run* [q] (insert 1 [2 3] q)) => '((1 2 3))) 
    (fact "We can retrieve the inserted data" 
     (run* [q] (insert q [2] '(1 2))) => '(1)) 
    (fact "We can retrieve the list data, too" 
     (run* [q] (insert 1 q '(1 2))) => '((2)))) 

我想我忽略了一些明顯的東西,但什麼?

編輯:事實並不能正確反映Prolog代碼的行爲。正確的做法是這樣的:

?- insert([2,3], 1, Q). 
    Q = [1, 2, 3] ; 
    Q = [2, 1, 3] ; 
    Q = [2, 3, 1]. 

因此,第二可檢查的實際上應該是

(fact "Inserting works" 
     (run* [q] (insert 1 [2 3] q)) => '((1 2 3) (2 1 3) (2 3 1))) 
+0

使用'NL = [H | R]'。在那裏不能使用'L'而不是'R','L'已經被用作參數。 –

回答

3

解決的辦法是做最後的遞歸插入子句:

(defn insert [x l nl] 
    (conde 
     [(conso x l nl)] 
     [(fresh [h t] 
     (conso h t l) 
     (conso h l nl) 
     (insert x t l))])) 
+0

謝謝。我將不得不考慮爲什麼改變順序在這裏有所作爲。 – schaueho

+0

爲了說明Prolog版本的正確行爲(參見上面我的編輯),'l'應該只用在第一個'conso'中,否則用新的'l1'代替。 – schaueho

3

序言碼可以幾乎逐字記錄爲core.logic也支持匹配。

(defne inserto [L, X, L*] 
    ([L, X, (X . L)]) 
    ([(H . T), X, (H . L)] (inserto T, X, L))) 

請注意,我保留了Prolog版本的順序,而不是版本中前兩個邏輯變量的倒序。

user=> (run* [q] (inserto [2] 1 q)) 
((1 2)) 
user=> (run* [q] (inserto [2 3] 1 q)) 
((1 2 3)) 
user=> (run* [q] (inserto [2] q [1 2])) 
(1) 
user=> (run* [q] (inserto q 1 [1 2])) 
((2)) 
+0

請注意@Ankur回答了真正的問題,但我認爲這是有用的指出和不適合的評論。 –

+0

感謝您在匹配中的提示,這確實使它更容易。然而,正如我發現的那樣,這種解決方案與Prolog版本的行爲不匹配,這可能會讓中間事實錯誤(我編輯了問題以糾正它)。然而,它只需要一個小的改變:在遞歸代碼中用'L'交換L1的使用,即'([H。T),X,(H。L1)])(inserto T,X,L1) '。這可以通過回溯來找到更多結果。 – schaueho