2011-06-17 57 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.