在树中用0替换叶原子,并在Prolog中列出

在树中用0替换叶原子,并在Prolog中列出,prolog,Prolog,我被以下Prolog代码困住了: islist([]). islist([A|B]) :- islist(B). memb([X|_]). memb([Y|Z]) :- islist(Y), memb(Y). memb([_|Z]) :- memb(Z). deep([],[]). deep([H|P],[M|N]) :- islist(H), deep(H,M), deep(P,N). deep([Y|P],[Y|N]) :-

我被以下Prolog代码困住了:

islist([]).
islist([A|B]) :-
   islist(B).

memb([X|_]).       
memb([Y|Z]) :- 
   islist(Y),
   memb(Y).
memb([_|Z]) :- 
   memb(Z).

deep([],[]).
deep([H|P],[M|N]) :-
   islist(H),
   deep(H,M),
   deep(P,N).
deep([Y|P],[Y|N]) :-
   number(Y),
   deep(P,N).
deep([H|P],[M|N]) :-
   atom(H),
   M is 0,
   deep(P,N).
deep([Y|P],[H|Q]) :-
   not(number(Y)),
   not(islist(Y)),
   not(atom(Y)),
   Y =.. T,
   deep(T,F),
   H =.. F,
   deep(P,Q),
   !.
当我试图运行它时,它给了我失败


我不能这样做。请帮忙。我不明白我错在哪里…

第一个问题是你误用了univ/2(即(=…)/2)。将最后一个子句更改为

deep([Y|P],[H|Q]):-
    not(number(Y)),
    not(islist(Y)),
    not(atom(Y)),
    Y=..[T|YArgs],
    deep(YArgs,HArgs),
    H=..[T|HArgs],
    deep(P,Q),!.
你将获得所需的行为

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))]

请注意,作为last子句的最后一个目标的cut无效。它完全没有用,但它的用法表明您需要进一步研究Prolog执行模式。

第一个问题是您误用了univ/2(即(=…)/2)。将最后一个子句更改为

deep([Y|P],[H|Q]):-
    not(number(Y)),
    not(islist(Y)),
    not(atom(Y)),
    Y=..[T|YArgs],
    deep(YArgs,HArgs),
    H=..[T|HArgs],
    deep(P,Q),!.
你将获得所需的行为

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))]

请注意,作为last子句的最后一个目标的cut无效。它完全没有用,但它的用法表明您需要进一步研究Prolog执行模式。

当我简单地获取您的程序,加载它,忽略单例警告并跟踪它时,我最终得到:

Call: (14) _G2807=..[0, 16, [0]] ? creep
ERROR: =../2: Type error: `atom' expected, found `0' (an integer)
   Exception: (14) _G2807=..[0, 16, [0]] ? 
所以,每次你得到一个函子,你首先分解它,就像这样:

foo(1, bar) ---> [foo, 1, bar] % in your code: Y=..T
然后将原子替换为0:

[foo, 1, bar] ---> [0, 1, 0] % in your code: deep(T,F)
然后出于某种原因,你又尝试用它来做一个函子:

[0, 1, 0] ---> 0(1, 0) % in your code: H=..F
这当然不起作用,而且这不是你想要的,似乎:

foo(1, bar) ---> foo, [1, bar] % Y =.. [Name|Args]
然后,您只能转换列表:

[1, bar] ---> [1, 0] % deep(Args, Args1)
并重新命名为:

foo, [1, 0] ---> foo(1, 0) % H =.. [Name|Args1]
通过程序中的这些更正:

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))] ;
false.
但是你可以让程序简单一点。首先,我认为你不需要你定义的
memb/1
:摆脱它。然后,您还可以在该定义中使用另一个子句:

islist(X) :-
    var(X), !,
    fail.
islist([]).
islist([_|T]) :-
    islist(T).
一种稍微清理其余代码的方法是编写:

deep([], []).
deep([X|Xs], [Y|Ys]) :-
    once( deep_1(X, Y) ),
    deep(Xs, Ys).

deep_1(X, Y) :- islist(X), deep(X, Y).
deep_1(X, X) :- number(X).
deep_1(X, 0) :- atom(X).
deep_1(X, Y) :- compound(X),
    X =.. [Name|Args],
    deep(Args, Args1),
    Y =.. [Name|Args1].
如您所见,目前,如果您有一个变量(或任何其他未识别的术语),程序将失败:

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))].

?- deep([14,Dog,a(b,27,c(16,[g]))],A).
false.
只需添加类型,即可轻松扩展程序:

deep_1(X, X) :- string(X).
然后:

?- deep([14,"Dog",a(b,27,c(16,[g]))],A).
A = [14, "Dog", a(0, 27, c(16, [0]))].

?- deep([14,Dog,a(b,27,c(16,[g]))],A).
false.

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))].

当我简单地获取您的程序,加载它,忽略singleton警告并跟踪它时,我最终得到:

Call: (14) _G2807=..[0, 16, [0]] ? creep
ERROR: =../2: Type error: `atom' expected, found `0' (an integer)
   Exception: (14) _G2807=..[0, 16, [0]] ? 
所以,每次你得到一个函子,你首先分解它,就像这样:

foo(1, bar) ---> [foo, 1, bar] % in your code: Y=..T
然后将原子替换为0:

[foo, 1, bar] ---> [0, 1, 0] % in your code: deep(T,F)
然后出于某种原因,你又尝试用它来做一个函子:

[0, 1, 0] ---> 0(1, 0) % in your code: H=..F
这当然不起作用,而且这不是你想要的,似乎:

foo(1, bar) ---> foo, [1, bar] % Y =.. [Name|Args]
然后,您只能转换列表:

[1, bar] ---> [1, 0] % deep(Args, Args1)
并重新命名为:

foo, [1, 0] ---> foo(1, 0) % H =.. [Name|Args1]
通过程序中的这些更正:

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))] ;
false.
但是你可以让程序简单一点。首先,我认为你不需要你定义的
memb/1
:摆脱它。然后,您还可以在该定义中使用另一个子句:

islist(X) :-
    var(X), !,
    fail.
islist([]).
islist([_|T]) :-
    islist(T).
一种稍微清理其余代码的方法是编写:

deep([], []).
deep([X|Xs], [Y|Ys]) :-
    once( deep_1(X, Y) ),
    deep(Xs, Ys).

deep_1(X, Y) :- islist(X), deep(X, Y).
deep_1(X, X) :- number(X).
deep_1(X, 0) :- atom(X).
deep_1(X, Y) :- compound(X),
    X =.. [Name|Args],
    deep(Args, Args1),
    Y =.. [Name|Args1].
如您所见,目前,如果您有一个变量(或任何其他未识别的术语),程序将失败:

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))].

?- deep([14,Dog,a(b,27,c(16,[g]))],A).
false.
只需添加类型,即可轻松扩展程序:

deep_1(X, X) :- string(X).
然后:

?- deep([14,"Dog",a(b,27,c(16,[g]))],A).
A = [14, "Dog", a(0, 27, c(16, [0]))].

?- deep([14,Dog,a(b,27,c(16,[g]))],A).
false.

?- deep([14,dog,a(b,27,c(16,[g]))],A).
A = [14, 0, a(0, 27, c(16, [0]))].

谢谢。这真的很有帮助。非常感谢。这真的很有帮助。谢谢你澄清我的想法。我正在NU prolog上尝试这个。该代码非常适合SW-prolog。感谢您澄清我的概念。我正在NU prolog上尝试这个。该代码非常适合SW prolog。