2014-06-29 119 views
3

因此,我有一個程序,它有一個謂詞,用給定的新元素替換列表中某個元素的第一個出現,併產生一個新列表。我已經完成它像這樣:序言 - 替換列表元素

changeFst(OldE,[OldE|T],NewE,[NewE|T]):-!. 
    changeFst(OldE,[_|T],NewE,_):- changeFst(OldE,T,NewE,_),!. 

例如,如果你給(2,[1,2,3,4,2],10,X)它應該給你回X = [1 ,10,3,4,2]

現在我正在改變最後一次出現的部分(在這個例子中它將返回X = [1,2,3,4,10])。這裏是我的代碼:

changeLast(OldE,OldL,NewE,NewL):- 
     reverse(OldE,X), 
     changeFst(OldE,X,NewE,NewL), 
     !. 

所以這個完美的作品其實但事情是它返回我扭轉了名單(在我上方的例子,它返回我[10,4,3,2,1]代替[1,2,3,4,10]

我該如何反過來讓我的答案正確顯示?

+0

你的定義不正確:'changeFst(鄰,[O, o],n,[o,n])。'成功了,但根據你的描述,它應該失敗! – false

+0

即使'changeFst(鄰,[O,O-]中,n,[])。'成功這顯然應該失敗。 – false

回答

3

您的changeFst/4的定義在很多方面不正確,例如changeFst(o,[o,o],n,[m,y,s,t,e,r,y]).成功,但顯然它會失敗。原因是你對裁剪的不正確使用。如果你想學習Prolog,請先堅持純粹的聲明性子集。這意味着沒有削減,也沒有副作用。

所以在這裏是不依賴於削減一個定義:

這樣一個純粹的關係
changeFst(Old,[Old|Olds],New,[New|Olds]). 
changeFst(Old,[E|Olds],New,[E|News]):- 
    dif(Old, E), 
    changeFst(Old,Olds,New,News). 

一個好處是,我們可以用最普通的查詢,看看有什麼答案,我們得到:

| ?- changeFst(Old, Olds, New, News). 
Olds = [Old|_A], 
News = [New|_A] ? ; 
Olds = [_A,Old|_B], 
News = [_A,New|_B], 
prolog:dif(Old,_A) ? ; 
Olds = [_A,_B,Old|_C], 
News = [_A,_B,New|_C], 
prolog:dif(Old,_A), 
prolog:dif(Old,_B) ? ; 
Olds = [_A,_B,_C,Old|_D], 
News = [_A,_B,_C,New|_D], 
prolog:dif(Old,_A), 
prolog:dif(Old,_B), 
prolog:dif(Old,_C) ? ... 

你注意到答案總是包含:Olds a 部分列表?像: Olds = [Old|_A]在第一個答案。這可能是有點太一般了,畢竟這意味着,即使nonlists正在接受:

| ?- changeFst(o,[o|nonlist], New, News). 
News = [New|nonlist] ? 
yes 

所以,你可能希望確保OldsNews總是列出。

但是我的觀點是,你要向你展示一個純粹的關係,你會看到很多事情,一個被切斷的程序永遠不會直接告訴你。

如果我們在這裏:如何處理空白列表?目前的版本暗示changeFst/4應該失敗。不知道你想要什麼,但如果你想要它成功,首先添加一個事實changeFst(_,[],_,[]).

請參閱this answer定義dif/2)如果您的Prolog不支持它。

1

(=)/3一起保持純淨和有效的,通過使用if_/3提議@false:

changeFst(Old,Olds,New,News) :- 
    list_change_first_(Olds,News,Old,New). 

list_change_first_([],[],_,_). 
list_change_first_([X|Xs],[Y|Ys],Old,New) :- 
    if_(X = Old, (Y = New, Ys = Xs), 
       (Y = X, list_change_first_(Xs,Ys,Old,New))). 

示例查詢:

?- changeFst(2,[1,2,3,4,2],10,Xs). 
Xs = [1,10,3,4,2].       % succeeds deterministically 

?- changeFst(o,[o,o],n,[m,y,s,t,e,r,y]). 
false.          % expected result 

?- changeFst(Old,Olds,New,News). 
Olds = [],    News = []          ; 
Olds = [Old|_A],  News = [New|_A]         ; 
Olds = [_A],   News = [_A],   dif(_A,Old)    ; 
Olds = [_A,Old|_B], News = [_A,New|_B], dif(_A,Old)    ; 
Olds = [_A,_B],  News = [_A,_B],  dif(_A,Old), dif(_B,Old) ; 
Olds = [_A,_B,Old|_C], News = [_A,_B,New|_C], dif(_A,Old), dif(_B,Old) % and so on... 
+0

'%等等...'你有沒有更好的名字。理想情況下,[tag:prolog-toplevel]可以使用這種約定來表示查詢已停止。我認爲...... ......但我不是100%肯定的。 – false

+0

@false。如何使用SO按鍵標記?我見過你偶爾使用它們......關於如何使用它們的建議?例如,「Key」; vs「key enter」vs沒有按鍵被按下,但引發異常。 – repeat

+0

理想情況下,它應該是有效的Prolog語法,ASCII和由頂層打印 – false