2016-03-12 53 views
0

我做的序言名單some exercises,我已經讀過this的問題,看到了subtract/3實施。但我仍然有點困惑。如何綁定變量,而名單上的遞歸?

現在我想從給定的列表中刪除元素的所有occurrencies,並試了幾次後,我有這樣的:

% --- del all X occurrences from a list 

del_all_X(_, [], _). 
% unbinded T2 
del_all_X(X, [X|T], T2):- 
    del_all_X(X, T, T2). 
    %!. ERROR: see below 
del_all_X(Y, [X|T], [X|T2]):- 
    dif(Y, X), % USE this instead of ! 
    del_all_X(Y, T, T2). 

這給了我這種類型的輸出:

25 ?- del_all_X(x, [x,a,b,x,d,e,x,x], X). 
X = [a, b, d, e|_G4115]. 
  • 這是思想的正確方法,同時結合自由變量(如 T2_)?
  • 如何有乾淨輸出?

回答:del_all_X(_,[],[])。

  • 有沒有caling外部功能更簡單的實現?

感謝


編輯:加改正,並在問題和代碼的答案。

+2

你得到的非實例尾巴在結果的原因是因爲你的基礎情況下它說,'del_all_X(_,[] _)'。如果你從空列表中刪除任何東西,你會得到一個匿名列表('_')。我不確定我是否理解你的評論,你想*在此解綁定'T2' *,因爲整個問題是將'T2'綁定到給定謂詞子句的結果。從邏輯上講,如果從空列表中刪除任何元素,則可能希望它導致空列表。所以這應該是'del_all_X(_,[],])。'。欲瞭解更多通用性,擺脫切('!')和使用'dif'。 – lurker

+0

謝謝del_all_X(_,[],[])。解決了這個小問題。 我的意思是從上面列出的教程中,不清楚如何管理輸出變量。我錯誤地認爲,在基本情況下,所有輸出列表都存儲在哪裏。 – bastaPasta

+0

我加了!爲了消除X仍然存在的其他輸出情況,我只想要完整的答案,即第一個答案。 編輯:你說得對,它也是這樣。 – bastaPasta

回答

1
  • 對於我已經理解了使用是不恰當的,因爲這可能會打斷意想不到的方式堆疊樹的生長,因爲它避免了與已經統一不同的值第二個規則的unifications由第一條規則。 learn prolog now - cut

  • DIF採用是必要的,因爲它避免了第二規則的統一時所搜索的元素(Y)比第一給定列表(X)的不同,在這種情況下主叫與該元件不同的變量是不夠的。 @false給出的例子闡明瞭。 見Using \== or dif

    % With ! and Without dif 
    [debug] ?- del_all_X(x, [x], [x]). 
    T Call: (7) del_all_X(x, [x], [x]) 
    T Call: (8) del_all_X(x, [], [x]) 
    T Fail: (8) del_all_X(x, [], [x]) 
    T Redo: (7) del_all_X(x, [x], [x]) 
    T Call: (8) del_all_X(x, [], []) 
    T Exit: (8) del_all_X(x, [], []) 
    T Exit: (7) del_all_X(x, [x], [x]) 
    true . 
    

    更新版本:

    del_all_X(_, [], []). 
    del_all_X(X, [X|T], T2):- 
        del_all_X(X, T, T2). 
    del_all_X(Y, [X|T], [X|T2]):- 
        % X \== Y 
        dif(Y, X),  
        del_all_X(Y, T, T2). 
    
    
    [debug] 7 ?- del_all_X(x, [x], [x]). 
    T Call: (7) del_all_X(x, [x], [x]) 
    T Call: (8) del_all_X(x, [], [x]) 
    T Fail: (8) del_all_X(x, [], [x]) 
    T Redo: (7) del_all_X(x, [x], [x]) 
    T Fail: (7) del_all_X(x, [x], [x]) 
    false. 
    
+1

很好。現在檢查你的最終版本是如何輕鬆地以一種聲明的方式被理解**:如果元素是相同的**,那麼該元素不會出現在第三個列表中。但是,如果他們**不同**('dif/2'),則元素**會出現在第三個列表中。這就是Prolog的全部內容:描述事物之間的**關係**。忘記關注痕跡的書。它們通常會導致一般不起作用的代碼。嘗試閱讀使用Prolog充分發揮潛力的材料,使用像'dif/2'這樣的陳述性謂詞和其他容易理解的約束條件。 – mat

+0

謝謝,這就是爲什麼我不喜歡Learn Prolog Now教程,這裏有太多的練習和很少的理論背景解釋。但閱讀速度很快。你能聯繫我一個更好的資源嗎? – bastaPasta

+1

爲了獲得更好的資源,請從[** Prolog優秀代碼**的特性](http://stackoverflow.com/a/15710541/1613573)開始,其他[false false頁面上的鏈接](http://stackoverflow.com/users/772868/false)和[**通過重複**得到的答案](http://stackoverflow.com/users/4609915/repeat?tab=answers),這些常常展示如何以一種非常一般的方式解決任務。 – mat