1

我试图编写一个 Prolog 脚本,它可以创建一个字符串列表,在一个简单的过程之后会产生一个给定的字符串。我对 Prolog 的了解非常有限,我什至不确定它是否能够执行此操作,所以请告诉我是否不可能。

到目前为止我得到了这个

replace_word(Old, New, Orig, Replaced) :-
    atomic_list_concat(Split, Old, Orig),
    atomic_list_concat(Split, New, Replaced).

它可以执行此操作

10 ?- replace_word('a','e','glava',X).
X = gleve.

但它不能回溯它

11 ?- replace_word('a','e',X,'gleve').
ERROR: atomic_list_concat/3: Arguments are not sufficiently instantiated

我可以想象是什么导致了这个问题,但是有没有办法解决它?

4

2 回答 2

1

replace_word/4 was written that way for efficiency, due to SWI-Prolog first class handling of atoms. To 'reverse' its semantic, I can't see a better way than using an helper predicate:

replace_word(Old, New, Orig, Replaced) :-
    (   var(Orig)
    ->  atomic_list_concat(L, New, Replaced),
        insert_alt(L, [Old, New], L1),
        atomic_list_concat(L1, Orig)
    ;   atomic_list_concat(L, Old, Orig),
        atomic_list_concat(L, New, Replaced)
    ).
insert_alt([A,B|R], Ks, [A,K|T]) :-
    member(K, Ks),
    insert_alt([B|R], Ks, T).
insert_alt([A], _Ks, [A]).

insert_alt/3 it's a bit more general than required, instead of a list (Ks) the pair of Old-New could be used....

test:

?- replace_word('a','e',X,'gleve').
X = glava ;
X = glave ;
X = gleva ;
X = gleve ;
false.
于 2012-07-31T09:14:54.203 回答
1

当然在实现这一点时应该有其他选择,而且我不是 Prolog 专家,但它似乎atomic_list_concat/3不会接受两个变量作为参数(考虑到这个谓词的作用,它会很棘手,对吧?),所以你可以绕过通过更改子句的顺序以“修复”您之前知道的变量来获得变量的问题。例如:

replace_word(Old, New, Orig, Replaced) :-
    (var(Orig), !, atomic_list_concat(Split, New, Replaced),
     atomic_list_concat(Split, Old, Orig)) ;
    (atomic_list_concat(Split, Old, Orig),
     atomic_list_concat(Split, New, Replaced)).

请注意,剪切不是必需的,但现在您可以按照您的要求进行操作:

?- replace_word('a','e',X,'gleve').
X = glava.

?- replace_word('a','e','glava',Y).
Y = gleve.
于 2012-07-27T23:18:52.803 回答