2011-06-17 61 views
4

我想出瓦特/下面的代碼替換的Find所有出現W/ReplaceRequest &把答案Result。這是使用DCG,因此它們都是字符代碼的列表。客戶端代碼將使用的謂詞是substitute查找和替換 - 代碼審查

findReplace(_, _, [], []) --> 
    []. % The end. 
findReplace(Find, Replace, Result, ResultRest) --> 
    Find, % Found Find. 
    { append(Replace, Intermediate, Result) }, % Put in Replace in Find's place. 
    !, % Make sure we don't backtrack & interpret Find as the next case. 
    findReplace(Find, Replace, Intermediate, ResultRest). 
findReplace(Find, Replace, [ C | Intermediate ], ResultRest) --> 
    [ C ], % Any other character. 
    findReplace(Find, Replace, Intermediate, ResultRest). 

substitute(Find, Replace, Request, Result):- 
    phrase(findReplace(Find, Replace, Result, []), Request). 

這適用於SWI-Prolog。有沒有人對我如何改進它有任何意見?我正在學習如何使用DCG的&差異列表。例如,我加入了切入點,以便在找到Find之後,prolog不會回溯&,將其解釋爲[ C ]情況下的普通字符。這是否需要,還是有更多的聲明方式呢?

另一個問題 - 是否有一個謂詞已經可以做同樣的事情,替代呢,也許在原子上呢?

在此先感謝。

回答

10

考慮使用semicontext符號在DCG中,以取代的子序列:

eos([], []). 

replace(_, _) --> call(eos), !. 
replace(Find, Replace), Replace --> 
     Find, 
     !, 
     replace(Find, Replace). 
replace(Find, Replace), [C] --> 
     [C], 
     replace(Find, Replace). 

substitute(Find, Replace, Request, Result):- 
     phrase(replace(Find, Replace), Request, Result). 

實施例:

?- substitute("a", "b", "atesta", R), atom_codes(A, R). 
R = [98, 116, 101, 115, 116, 98], 
A = btestb. 

另外,underscores_are_much_more_readable thanMixedCaseNamesAsYouSee。

+1

這是巧妙。順便說一句,我注意到,這擴展到以下。 替換(_,_,A,B): - call(eos,A,C),!, B = C。 (A,D,B,F)替代(A,D,B,F): 短語(A,B,C), E = C, 替換)。 替代(B,C,A,E): A = [F | D] 替代(A,B,C,D): - 短語(替代(A,B),C,D)。 eos([],[])。 這是尾部遞歸嗎?在第一次遞歸替換調用和第二次後的列表綁定之後有一個'phrase'調用。 – Ashley

+0

在該示例中,短語/ 3將翻譯並執行「a」和「b」。該解決方案效率不高,因爲翻譯會重複一遍又一遍。不知道該修復會是什麼。 –

2

關於第二個問題,即,與工作原子,我寫該實用程序細讀atomic_list_concat

%% replace_word(+Old, +New, +Orig, -Replaced) 
%% is det. 
% 
% string replacement 
% doesn't fail if not found 
% 
replace_word(Old, New, Orig, Replaced) :- 
    atomic_list_concat(Split, Old, Orig), 
    atomic_list_concat(Split, New, Replaced). 

實施例:

?- replace_word(a, b, atesta, X). 
X = btestb.