List 替换列表序言中的术语

List 替换列表序言中的术语,list,replace,prolog,List,Replace,Prolog,我正在尝试编写一个prolog程序,它将接受一个列表、一个旧的_子项和一个新的_子项作为输入,并返回一个新的列表,其中旧的_子项的每个实例都已替换为新的_子项。 比如说 | ?- sub_rep([h(A,g(x)),g(x),g(3)],g(x),p,T). T = [h(A,p),p,g(3)] ? ; no 因此,我可以使用以下代码将其用于基本列表: replace(E,S,[],[]). replace(E,S,[E|T1],[S|T2]):- replace(E,S,T1,T

我正在尝试编写一个prolog程序,它将接受一个列表、一个旧的_子项和一个新的_子项作为输入,并返回一个新的列表,其中旧的_子项的每个实例都已替换为新的_子项。 比如说

| ?- sub_rep([h(A,g(x)),g(x),g(3)],g(x),p,T).
T = [h(A,p),p,g(3)] ? ;
no
因此,我可以使用以下代码将其用于基本列表:

replace(E,S,[],[]).
replace(E,S,[E|T1],[S|T2]):-
    replace(E,S,T1,T2).
replace(E,S,[H|T1],[H|T2]):-
    E\=H, 
    replace(E,S,T1,T2).

%(here's some example input/output)

?- replace(b,e,[a,b,c],L).
L = [a, e, c] ;
false.

?- replace(f(Y),g(Y),[f(Y),1,2,f(Y)],L).
L = [g(Y), 1, 2, g(Y)] ;
false.
但当我尝试使用更复杂的列表时,例如

?- replace(g(Y),h,[f(g(Y)),g(Y),g(1)],L).
我得到以下答案:

Y = 1,
L = [f(g(1)), h, h] ;
false.
这不是我想要的,因为我希望它能回来:

? - L = [f(h),h,g(1)] ;
false.
我不熟悉prolog,可能遗漏了一些明显的东西,但我不明白为什么在这种情况下要实例化变量Y?在第二个例子中,这似乎不是问题。我想这与g(1)的出现有关,但我不明白为什么?
提前感谢!:)

你应该“爆炸”你的术语进行比较

replace(_, _, [], []).
replace(E, S, [X|T1], [Y|T2]):-
    replace_term(E, S, X, Y),
    !, replace(E, S, T1, T2).
replace(E,S, [H|T1], [H|T2]):-
    replace(E,S,T1,T2).

replace_term(E, S, E, S) :- !.
replace_term(E, S, T, R) :-
      T =.. [F|As],  % explode
      replace(E, S, As, Gs),
      R =.. [F|Gs].  % reassemble
测试:

当模式中存在变量时,事情会变得更复杂:

?- replace(g(Y),h,[f(g(Y)),g(Y),g(1)],L).
Y = 1,
L = [f(h), h, h] ;

也许能有所帮助,或者我们必须设计一种策略,立即实例化变量…

您应该“分解”您的术语以进行比较

replace(_, _, [], []).
replace(E, S, [X|T1], [Y|T2]):-
    replace_term(E, S, X, Y),
    !, replace(E, S, T1, T2).
replace(E,S, [H|T1], [H|T2]):-
    replace(E,S,T1,T2).

replace_term(E, S, E, S) :- !.
replace_term(E, S, T, R) :-
      T =.. [F|As],  % explode
      replace(E, S, As, Gs),
      R =.. [F|Gs].  % reassemble
测试:

当模式中存在变量时,事情会变得更复杂:

?- replace(g(Y),h,[f(g(Y)),g(Y),g(1)],L).
Y = 1,
L = [f(h), h, h] ;

也许我们能帮上忙,或者我们必须设计一种策略,立即实例化变量…

对您的问题的第一个观察:列表长度相同!这听起来像是
maplist/3
的一个很好的候选者

replace(A, B, As, Bs) :-
   maplist(repl(A,B), As, Bs).
问题的“递归”部分到此为止。现在,我们必须定义
repl/4
。 以下是我对你想要什么的猜测:

repl(A, B, A0, B0) :-
   ( A == A0 -> B = B0 ; A0 = B0 ).

也许你需要一些其他的测试来代替
(==)/2

对你的问题的第一个观察:列表长度相同!这听起来像是
maplist/3
的一个很好的候选者

replace(A, B, As, Bs) :-
   maplist(repl(A,B), As, Bs).
问题的“递归”部分到此为止。现在,我们必须定义
repl/4
。 以下是我对你想要什么的猜测:

repl(A, B, A0, B0) :-
   ( A == A0 -> B = B0 ; A0 = B0 ).

也许你需要一些其他的测试来代替
(==)/2

我知道这是一个更好的方法,但是我仍然遇到上面的错误,也就是说?-替换(g(Y),h,[f(g(Y)),g(Y),g(1)],L)。Y=1,L=[f(g(1)),h,h];错。你有没有想过为什么会这样?再次感谢!我知道这是一个更好的方法,但是我仍然遇到上面的错误,也就是说?-替换(g(Y),h,[f(g(Y)),g(Y),g(1)],L)。Y=1,L=[f(g(1)),h,h];错。你有没有想过为什么会这样?再次感谢!啊!!!我完全忘了地图列表!非常感谢你提醒我!:)希望现在航行会更顺利!好吧,我已经盯着这个看了一段时间了,我还是有点撞到墙了。为了确保我没有感到困惑,我是否正确地认为这与上述代码的工作原理类似?我们使用maplist/3来应用“部分目标”,repl。我们给repl我们想要替换的术语和我们想要替换的术语,如果A恰好是列表中的那个术语,我们用B替换它,否则我们保留它。假设这是正确的,我遇到了嵌套化合物的问题,例如,我似乎无法替换[s(f(a,b,g(X))中的g(X)].有什么想法吗?为什么?只替换列表中的元素,而不是子项。但您在原来的帖子中没有要求这样做。啊,是的,我很抱歉!我也想替换子项。我认为用另一个函数调用替换repl/4中的'a==A0'部分是一种合理的方法,首先检查wh以太A==A0,如果不是,则检查A0是否为化合物,如果是,则检查它是否为化合物,并将其返回到列表并递归?啊!!我完全忘记了maplist!非常感谢您的提醒!:)希望它现在(更顺利)航行!好吧,我已经盯着这个看了一段时间了,我还是有点撞到墙了。为了确保我没有感到困惑,我是否正确地认为这与上述代码的工作原理类似?我们使用maplist/3来应用“部分目标”,repl。我们给repl我们想要替换的术语和我们想要替换的术语,如果A恰好是列表中的那个术语,我们用B替换它,否则我们保留它。假设这是正确的,我遇到了嵌套化合物的问题,例如,我似乎无法替换[s(f(a,b,g(X))中的g(X)].有什么想法吗?为什么?只替换列表中的元素,而不是子项。但您在原来的帖子中没有要求这样做。啊,是的,我很抱歉!我也想替换子项。我认为用另一个函数调用替换repl/4中的'a==A0'部分是一种合理的方法,首先检查wh乙醚A==A0,如果不是,则检查A0是否为化合物,如果是,则检查它是否为一个列表并递归?