使用prolog DCG查找&替换 - 代码审查

时间:2011-06-17 23:16:43

标签: prolog dcg

我出现了以下代码,以替换Find中所有Replace w / Request的出现。把答案放在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 ]案例中的普通字符。这是否需要,或者是否有一种更具说明性的方式呢?

另一个问题 - 是否有一个谓词已经可以用替代品做同样的事情,可能是在原子上?

提前致谢。

2 个答案:

答案 0 :(得分: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 :(得分: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.