我的任務是寫謂詞subst(T,A,V,R)
改變原子A
的所有出現在表達T
到原子V
並且將結果呈現爲R
。序言,在表情變化原子
例如:
subst(object(one, two),one,three,R). //R=object(three,two).
susbt(a+1,a,2,R). //R=2+1.
它可以很容易與方法:我改變表達式中使用T=..L
列出,然後我的L
每個元素比較A
,如果它們是相同的,我可以將其更改爲V
。最後,我可以逆轉第一個動作(重新獲得表達式),但我不知道如何處理如下情況: subst((a+1)*(b+3),a,2,W)
。 //?喜歡的東西T=..L
開始
我可以得到[*,a+1,b+3]
,但現在如果我想改變a
到2
,我無法檢查的L
每個連續的項目,因爲他們中的一些並不簡單原子/數字。現在我的問題是,是否有任何內置的謂詞來檢查列表中的元素是否如下所示:a
,1
等,但不是a+1
?我的意思是如果我不想先檢查它是否是原子,那麼後來如果它不是。
或者也許有更簡單的方法來解決這個問題?
編輯1: 感謝您的意見。我至今:
subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R).
make_simple([],[]).
make_simple([H|T],[H|W]):-atom(H),make_simple(T,W),!.
make_simple([H|T],[H|W]):-number(H),make_simple(T,W),!.
make_simple([H|T],[W1|W2]):- \+atom(H),\+number(H),H=..H1,make_simple(H1,W1),make_simple(T,W2).
replace([],_,_,[]).
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!.
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!.
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!.
to_exp([],[]).
to_exp([H|T],[H|W]):- \+is_list(H),to_exp(T,W),!.
to_exp([H|T],[W1|W2]):- is_list(H), (what next?)
不幸的是,我不知道如何把這些AP拼湊現在to_exp
一部分。特別是當它像:
to_exp([*,[+,a,1],[-,3,b]]).
甚至更糟:
to_exp([*,[+,[*,4,2],1],[-,3,b]]).
我的意思是,如果外部列表的元素是一個列表,我不知道如何識別它的準確三個元素的列表,其中每個元素都是一個原子/數字。任何提示?:)
EDIT2
好吧,我被告知,它變得過於複雜。也許吧,但我是Prolog的新手,我只使用迄今爲止學到的工具/技術,因爲我應該完成的任務是以這種方式構建的。當然,必須有更簡單的方法,就像@mat所建議的那樣,但我至今尚未對dif
或maplist
謂詞有所瞭解。這就是爲什麼我決定以這種方式繼續這一個。
我發現沒有必要單獨檢查和number
。有atomic/1
,如果一個術語是數字,原子或en空列表(因此@mat關於SWI-Prolog提到的問題似乎並不重要)返回true。在此之後,我已經改變了先前的謂詞和我已經完成to_exp
爲:
subst(T,A,V,R):-T=..L,make_simple(L,L1),replace(L1,A,V,L2),to_exp(L2,R).
make_simple([],[]).
make_simple([H|T],[H|W]):-atomic(H),make_simple(T,W),!.
make_simple([H|T],[W1|W2]):- \+atomic(H),H=..H1,make_simple(H1,W1),make_simple(T,W2),!.
replace([],_,_,[]).
replace([A|T],A,V,[V|W]):- replace(T,A,V,W),!.
replace([H|T],A,V,[H|W]):- H\=A,\+is_list(H),replace(T,A,V,W),!.
replace([H|T],A,V,[W1|W2]):-H\=A, is_list(H),replace(H,A,V,W1),replace(T,A,V,W2),!.
to_exp([],[]).
to_exp([Z,H1,H2],L):-atomic(H1),atomic(H2),L=..[Z,H1,H2],!.
to_exp([Z,H1,H2],L):- \+atomic(H1),atomic(H2),to_exp(H1,W1),L=..[Z,W1,H2].
to_exp([Z,H1,H2],L):- atomic(H1),\+atomic(H2),to_exp(H2,W1),L=..[Z,H1,W1].
to_exp([Z,H1,H2],L):- \+atomic(H1),\+atomic(H2),to_exp(H1,W1),to_exp(H2,W2),L=..[Z,W1,W2].
現在,既適用函子和參數,簡單和嵌套的。 無論如何,感謝您的影響,我將來肯定會考慮使用dif
和maplist
。歡呼:)
你在正確的軌道上。你可以使用'atom/1':如果它的參數是一個原子,則爲真。注意:這是一個非單調謂詞,所以只有當參數被充分實例化時才使用它。例如,參見「原子(X)」,X =「與原子(X)」。 – mat
爲什麼不使用'= ..'遞歸地分解它呢?所以'(a + 1)*(b + 3)'導致'[*,a + 1,b + 3]',並且每個元素都會導致'[*]',[+,a,1] '和'[+,b,3]'。在最底層,你可以找到你的原子來代替。你可以使用mat的想法來使用'atom'來知道你什麼時候「觸底」。如果'X'是一個數字,'number(X)'是真的。 – lurker
您希望'subst(foo(a,b),foo,bar,R).'工作嗎?它應該失敗嗎?它應該用'R = foo(a,b)'成功嗎?還是應該用'R = bar(a,b)'成功? – lurker