2013-11-04 226 views
2

我對Prolog非常陌生,正試圖弄清究竟發生了什麼事情(函數?),它取出列表中倒數第二個元素。取出倒數第二個元素 - Prolog

remove([],[]). 
remove([X],[X]). 
remove([_,X],[X]). 
remove([X|Xs], [X|Ys]) :- 
    Xs = [_,_|_], 
    remove(Xs,Ys). 

我熟悉模式匹配,因爲我在SML中做了一些工作。第一個顯然是基本情況,當我們分解時返回空列表。當只剩下一個時,第二個返回相同的變量。第三看起來好像它返回最後一個元素,無視第二個到最後?至於歸納情況,如果......(這是我完全失去的地方),它會將列表頭添加到新列表中。任何人都可以解釋這個函數發生了什麼,所以我可以更好地理解這個語言嗎?

回答

2

一組子句謂詞,或過程

所有前三個都是基本情況,遞歸的副本,而第一個列表中至少有3個元素。

我會描述像'刪除前一個元素'的行爲。

3

在闡述CapelliC的解釋:

remove([],[]). 

空列表是空列表與第二個到最後移除的元素。

remove([X],[X]). 

單元素列表本身是倒數第二個元素。

remove([_,X],[X]). 

與第二至移除的最後一個元件的兩元素列表是由兩個元素的列表的最後一個元素中的一個元素的列表。

remove([X|Xs], [X|Ys]) :- 
    Xs = [_,_|_], 
    remove(Xs,Ys). 

的第二列表是所述第一列表移除了第二元件,並且共享相同的第一元件,IF:

  1. 第一列表的尾部包括至少兩個元素,並且
  2. 第二列表的尾部是第一列表的尾部與所述第二到最後一個元素除去
0

註釋:

remove([]  , [] ) . % removing the 2nd last element from the empty list yields the empty list 
remove([X] , [X] ) . % removing the 2nd last element from a 1-element list yields the 1-element list. 
remove([_,X] , [X] ) . % removing the 2nd last element from a 2-element list yields the tail of the 2-element list 
remove([X|Xs] , [X|Ys]) :- % for any other case... 
    Xs = [_,_|_],    % * if the tail contains 2 or more elements, the list is 3 elements or more in length 
    remove(Xs,Ys).    % we simply prepend the head of the list to the result and recurse down. 

應當注意的是,最後一句可以重新寫一點點更清晰(多一點簡潔)爲:

remove([X1,X2,X3|Xs] , [X1|Ys]) :- % for any other case (a list of length 3 or more) 
    remove([X2,X3|Xs],Ys).    % we simply prepend the head of the list to the result and recurse down. 

或者作爲

remove([X1|[X2,X3|Xs]] , [X1|Ys]) :- % for any other case (a list of length 3 or more) 
    remove([X2,X3|Xs],Ys).    % we simply prepend the head of the list to the result and recurse down. 
2

那麼,如何以聲明方式閱讀

remove([X|Xs], [X|Ys]) :- 
    Xs = [_,_|_], 
    remove(Xs,Ys). 

最重要的是你第一次意識到什麼是012其實是指。

:-身體.

這意味着:每當身體成立,我們可以得出結論,也成立。注意箭頭的相當不直觀的方向。它從右到左。而不是從左到右,就像你在結束某些事情時經常寫的那樣。然而,這個錯誤指向了我們「走出去」的方向。

爲了更好地看到這個,你可以輸入Body作爲查詢!

?- Xs = [_,_|_], remove(Xs,Ys). 
Xs = [A, B], 
Ys = [B] ; 
Xs = [A, B, C], 
Ys = [A, C] ; 
... 

所以我們得到了所有的答案,除了那些Xs有不到兩個元素。

請注意,在程序上,事情發生在另一個方向 - 這對初學者來說非常混亂。更重要的是,因爲Prolog使用了兩個「非傳統」特徵:按時間順序回溯和變量 - 我的意思是real變量,意思是所有可能的術語 - 而不是從命令式和函數式語言中知道的這些編譯時構造。在這些語言中,變量是運行時值的持有者。具體的價值。在Prolog中,變量在運行時也存在。欲瞭解更多信息,請參閱Difference between logic programming and functional programming

另外還有一個問題,我不確定你是否理解。想想:

?- remove(Xs, [1,2]). 
Xs = [1, A, 2] ; 
false. 

這裏刪除了什麼?沒有!恰恰相反,我們正在向列表中添加更多元素。由於這個原因,名稱remove/2在Prolog中並不理想 - 它讓我們想起了命令式編程語言,它強制給出一些參數並計算其他參數。你可能會首先認爲這並不重要,畢竟它只是一個名字。但是不要忘記,編程時你經常沒有時間全盤考慮。所以一個好的關係名稱可能更可取。

要找到一個,請從類型開始:list_list/2,然後再細化​​或list__without_2nd_last/2

相關問題