将列表中的所有成员都包括在内,包括子列表Prolog,而不使用maplist

时间:2013-11-01 22:21:45

标签: list prolog

我是Prolog的新手并尝试实现一种深度方形谓词,它将列表中的所有数字以及子列表中的所有数字都对齐。我写了一些工作代码,但它没有给我预期的输出。

代码:

dsquare([],S).
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
dsquare([H|T],S):- isList(H), dsquare(H,S).
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.

当前输出:

2?- dsquare([[2],4,a],X).

X = [4| _VDHV] ;

X = [[2], 16, a| _VDNM] ;

fail.

预期产出:

  

X = [[4],16,a]

我也想知道为什么我的输出中会出现'_VDHV'和'_VDNM'。 任何帮助将不胜感激。

编辑: 好的,所以我将我的代码更新为:

dsquare([],[]).
dsquare([H|T],[R|S]):- number(H), R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]):- isList(H), dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).

但我得到的输出是:

13?- dsquare([a,3,[[2]],b,4],X).

X = [a, 9, [[4]], b, 16] ;

X = [a, 9, [[4]], b, 4] ;

X = [a, 9, [[2]], b, 16] ;

X = [a, 9, [[2]], b, 4] ;

X = [a, 9, [[2]], b, 16] ;

X = [a, 9, [[2]], b, 4] ;

X = [a, 9, [[2]], b, 16] ;

X = [a, 9, [[2]], b, 4] ;

X = [a, 3, [[4]], b, 16] ;

X = [a, 3, [[4]], b, 4] ;

X = [a, 3, [[2]], b, 16] ;

X = [a, 3, [[2]], b, 4] ;

X = [a, 3, [[2]], b, 16] ;

X = [a, 3, [[2]], b, 4] ;

X = [a, 3, [[2]], b, 16] ;

X = [a, 3, [[2]], b, 4] ;

fail.

我不知道它是如何得到这么多结果的。

修改的 最后,工作解决方案是

dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[H|S]) :- dsquare(T,S).

2 个答案:

答案 0 :(得分:0)

你的Prolog应该在第一和第三条规则中警告你“单身人士”。

尝试

dsquare([],[]).
...
dsquare([H|T],[S|R]):- isList(H), dsquare(H,S), dsquare(T,R).

OT不会在没有动机原因的情况下进行裁员。

编辑你会得到更多结果,因为最后一条规则被引发回溯。现在可以将剪切放置在需要的地方(即在代码进入由条件保护的分支之后):

dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).

或考虑重复代码的重构:

dsquare([],[]).
dsquare([H|T],[R|S]) :-
  (  number(H)
  -> R is H*H
  ;  isList(H)
  -> dsquare(H,R)
  ;  R=H
  ),
  dsquare(T,S).

编辑上面的定义(我用'if / then / else'测试过)似乎很好:

1 ?- dsquare([[2],4,a],X).
X = [[4], 16, a].

2 ?- dsquare([a,[3],[[[5]]],[2],a],X).
X = [a, [9], [[[25]]], [4], a].

答案 1 :(得分:0)

_Vxxx位是prolog对结果中未绑定变量的表示。基本上,它是符号表中的键或地址。

  • 在您的第一条规则中,

    dsquare([],S).
    

    你永远不会将任何东西绑定到第二个参数。这意味着如果您将其作为dsquare([],X)调用,则X将保持未绑定状态。如果调用为dsquare([1,2,3],X)(假设其他所有内容都正常工作,则结果列表结构将被破坏,X将类似[1,2,3|_VD3DC],因为最后一项不是atome [](空列表)或./2,结构为非空列表。

  • 在你的第二条规则中,

    dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
    
    • 不需要剪切(!
    • 您的运营商订单不正确。首先是方形H,然后递减。这完成了两件事:它(A)早期失败(如果结果是绑定的),(B)允许应用尾递归优化。
  • 在您的第3条规则中,

    dsquare([H|T],S):- isList(H), dsquare(H,S).
    

    您正在递归到作为源列表头部的子列表,但根本不评估源列表的尾部而是简单地丢弃它。

  • 在你的第4条规则中,

    dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
    

    再次,就像在你的第二条规则中一样,切割是不必要的,操作顺序也相反。

我写的是这样的:

deep_square( []     , []     )    % squaring an empty list produces an empty list
  .
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
  number(X) ,                     % if the head is a number,
  Y is X*X  ,                     % square it
  deep_square(Xs,Ys)              % and recurse down
  .                               %
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
  nonvar(X) ,                     % if the head is bound,
  X = [_|_] ,                     % and is a non-empty list.
  deep_square( X , Y ) ,          % deep square the head
  deep_square( Xs , Ys )          % and then recurse down
  .
deep_square( [X|Xs] , [X|Ys] ) :- % otherwise the head is unbound or something other than a number or a non-empty list...
  deep_square( Xs , Ys )          % recurse down.
  .                               % Easy!

你会注意到,在一个序言谓词的句子的头部发生了一个很多的统一魔法等。