5

我想出了以下代码来替换所有出现的Findw/ ReplaceinRequest并将答案放入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 ]案例中的普通字符。这是需要的,还是有一种更具声明性的方式?

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

提前致谢。

4

2 回答 2

11

考虑使用半上下文符号来替换 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.

此外,下划线比MixedCaseNamesAsYouSee 更具可读性。

于 2011-06-18T10:56:02.337 回答
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.
于 2012-10-07T12:17:29.463 回答