嵌套列表中的替换(prolog)

嵌套列表中的替换(prolog),prolog,Prolog,/*如果列表Ys是用Y替换列表Xs中所有出现的X的结果,则替换(X,Y,Xs,Ys)为真 这就是我到目前为止所做的: subs(_,_,[],[]). subs(X,Y,[X|L1],[Y|L2]):- subs(X,Y,L1,L2). subs(X,Y,[H|L1],[H|L2]):- X\=H, not(H=[_|_]), subs(X,Y,L1,L2). subs(X,Y,[H|_],[L2]):- X\=H, H=[_|_], subs(X,Y,H,L2). 我的代码可以工作,只是它忽

/*如果列表Ys是用Y替换列表Xs中所有出现的X的结果,则替换(X,Y,Xs,Ys)为真

这就是我到目前为止所做的:

subs(_,_,[],[]).
subs(X,Y,[X|L1],[Y|L2]):- subs(X,Y,L1,L2).
subs(X,Y,[H|L1],[H|L2]):- X\=H, not(H=[_|_]), subs(X,Y,L1,L2).
subs(X,Y,[H|_],[L2]):- X\=H, H=[_|_], subs(X,Y,H,L2).
我的代码可以工作,只是它忽略了嵌套列表后面的元素。例如:

?- subs(a,b,[a,[a,c],a],Z).
Z = [b, [b, c]] .

我应该向这个程序添加什么?

问题是,一旦找到嵌套列表,您就会忘记该嵌套列表后面的内容。相反,在使用嵌套嵌套进行递归之后,只需像以前一样继续。因此,您应将最后一条修改如下:

subs(X,Y,[H|L1],[H2|L2]):- X\=H, H=[_|_], subs(X,Y,H,H2), subs(X, Y, L1, L2).
除此之外,还有两种方法可以改进代码:

  • 使用(
    !/0
    )停止回溯。这样你就不必重复你自己了
  • 可以使用测试参数是否为列表
  • 可以使用更多的空间。真的
  • 因此,另一种解决方案是(现在使用而不是):

    演示:

    ?- subs(a, b, [a, [a, [d, f, a]], a, b, a, [g]], Z).
    Z = [b, [b, [d, f, b]], b, b, b, [g]].
    

    下面是如何使用(…->…;…)编写它:


    削减是丑陋的,它们隐藏了以下条款中隐含的否定。我发现使用(…->…;…)更好,这类似于函数式编程中的if-then-else。@starblue:是的,我隐约记得cut存在一些问题(直到最近我才重新对Prolog产生兴趣)。我将在不久的将来仔细阅读。谢谢你的提醒,我会投票给你的答案:)这是家庭作业:下次,请给它贴上这样的标签!
    ?- subs(a, b, [a, [a, [d, f, a]], a, b, a, [g]], Z).
    Z = [b, [b, [d, f, b]], b, b, b, [g]].
    
    subs(_, _, [], []).
    subs(X, Y, [H1|T1], [H2|T2]) :-
        (H1 == X ->
            H2 = Y
        ; is_list(H1) ->
            subs(X, Y, H1, H2),
            subs(X, Y, T1, T2)
        ;
            H1 = H2,
            subs(X, Y, T1, T2)
        ).