非平凡的 Prolog 查找和替换

问题描述:

所以我们可以很容易地在 Prolog 中找到一个原子并将其替换为另一个原子,方法如下:

So we can easily find and replace an atom with another atom in Prolog by doing something like:

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).

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

I'm sure there are other ways to do this too.

但是,我想在计算逻辑上做一些更复杂的事情.你会如何做一些事情,比如用 (x,y) 替换逻辑语句中像 conj(x,y) 这样的连词?所以它就像 final 和 replace 但不是用原子.所以我们可以有类似 reduce(conj(conj(x,y),z)). 的东西,我想减少到 ((x,y),z).

However, I want to do something more complicated in logic in computing. How would you do something like replacing conjunctions like conj(x,y) in a logical statement with just (x,y)? So it's like final and replace but not with atoms. So we could have something like reduce(conj(conj(x,y),z)). that I would want reducing to ((x,y),z).

这是一个只有连词的简单例子,但这就是我想要在连词的情况下发生的事情.如果有人感兴趣,这完全是关于描述性逻辑和表格方法.

This is a simple example with only conjunctions but this is what I want to happen in the case of conjunctions. If anyone's interested, this is all about descriptive logic and the tableau method.

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

What I'm confused about it how you go about doing a find and replace when the input isn't actually a list; it's a structure. I don't see how you can solve this without using the standard [H|T] trick with recursion and lists. Has anyone got any ideas?

非常感谢.

这是通过编写元解释器以一种直接的方式完成的,例如:

This is done in a straightforward way by writing a meta-interpreter, such as the following:

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].

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

Note the second last clause, which serves to perform a replacement of your specific case of replacing conj/2 with conjunction, ,/2. You can add as many other clauses in the same manner as this to perform term replacement in general, because the rest of the definition (all other clauses of replace/2) here will recursively deconstruct any PROLOG term, as we've covered all the types; vars, atoms, and compound terms (including lists explicitly).

在你的情况下执行这个给我们:

Executing this in your case gives us:

?- replace(conj(conj(x,y),z), NewTerm).
NewTerm = ((x, y), z).

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

Note that this definition will perform the correct replacement of any terms nested to arbitrary depth within another term.