非平凡的Prolog找到并替换

ale*_*ale 6 prolog

因此,我们可以通过以下方式轻松找到并用Prolog中的另一个原子替换原子:

replace([],A,B,[]).
replace([H|T],A,B,[B|Result]) :- 
    H=A, 
    replace(T,A,B,Result),!.
replace([H|T],A,B,[H|Result]) :- 
    replace(T,A,B,Result).
Run Code Online (Sandbox Code Playgroud)

我确信还有其他方法可以做到这一点.

但是,我想在计算中做一些更复杂的逻辑.你会怎么做像conj(x,y)在逻辑语句中用(x,y)替换连词?所以它就像是最终的,取而代之的是原子.所以我们可以有类似的东西reduce(conj(conj(x,y),z)).,我希望减少到((x,y),z).

这是一个只有连词的简单例子,但这是我想在连词的情况下发生的事情.如果有人感兴趣,这就是描述逻辑和画面方法.

当输入实际上不是列表时,我对如何进行查找和替换感到困惑; 这是一个结构.我没有看到如何在不使用[H|T]递归和列表的标准技巧的情况下解决这个问题.有没有人有任何想法?

非常感谢.

sha*_*rky 5

这是通过编写元解释器以直截了当的方式完成的,如下所示:

replace(V, V) :-
    % pass vars through 
    var(V), !.     
replace(A, A) :- 
    % pass atoms through 
    atomic(A), !.
replace([], []) :- 
    % pass empty lists through
    !.
replace([X|Xs], [Y|Ys]) :-
    % recursively enter non-empty lists
    !, 
    replace(X, Y),
    replace(Xs, Ys).
replace(conj(X,Y), (NX,NY)) :-
    % CUSTOM replacement clause for conj/2
    !, 
    replace(X, NX),
    replace(Y, NY).
replace(T, NT) :-
    % finally, recursively enter any as yet unmatched compound term
    T =.. [F|AL],
    replace(AL, NAL),
    NT =.. [F|NAL].
Run Code Online (Sandbox Code Playgroud)

请注意第二个最后一个子句,用于替换您conj/2使用连接替换的特定情况,/2.您可以以与此相同的方式添加任意数量的其他子句来执行术语替换,因为replace/2这里的定义的其余部分(所有其他子句)将递归地解构任何 PROLOG术语,因为我们已经涵盖了所有类型; 变量,原子和复合词(包括明确的列表).

在您的情况下执行此操作会给我们:

?- replace(conj(conj(x,y),z), NewTerm).
NewTerm = ((x, y), z).
Run Code Online (Sandbox Code Playgroud)

请注意,此定义将在另一个术语中执行嵌套到任意深度的任何术语的正确替换.