输入列表未在Prolog中获得

时间:2016-07-04 04:07:50

标签: prolog

我正在使用以下代码:

item(a, b, c).
item(a, a, c).
item(a, d, c).
item(a, c, b).

main:-
    getItems(L),
    writeln('-----------1-------------'),
    writeln(L),
    findall((A,B,C), item(A,B,C), M),
    writeln('-----------2-------------'),
    compareItem(M,L,I),
    writeln('-----------3-------------'),
    writeln(I).

getItems([Item|List]):-
    writeln('Enter:'),
    read(Item),
    dif(Item,stop),
    getItems(InputList).

getItems([]).

compareItem([H|T],L,Out):-
    writeln('-----------4-------------'),
    intersection(H,L,I),
    writeln('-----------5-------------'),
    compareItem(T,L,[I|Out]).
compareItem([],L,Out).

它提供以下输出:

?- main.
Enter:
|: a.
Enter:
|: b.
Enter:
|: stop.
-----------1-------------
[a|_G1003]
-----------2-------------
-----------4-------------
-----------1-------------
[a|_G1003]
-----------2-------------
-----------4-------------
-----------1-------------
[]
-----------2-------------
-----------4-------------
false.

4 ?-

输入法取自:Creating a list from user input with swi-prolog

当命令单独运行时,我会得到以下信息:

?- findall((A,B,C), item(A,B,C), M)
M = [ (a, b, c), (a, a, c), (a, d, c), (a, c, b)].
?- intersection([a,b,c],[a,b],I).
I = [a, b].

但是,M中的[(a,b,c),...]和我预期的用户输入为[a,b](此处为空白)。

我希望输出是用户输入与M:

中每个项目的交集
[(a,b), (a,a), (a), (a,b)]

此外,在到达第4点后,执行如何再次到达第1点?

如何纠正这些问题?谢谢。

2 个答案:

答案 0 :(得分:1)

您只获得第一个元素,因为您从不使用包含其余元素的列表:

getItems([Item|List]):-
    writeln('Enter:'),
    read(Item),
    dif(Item,stop),
    getItems(InputList).

看到过于粗体的变量?它们有不同的名称,但它们需要具有相同的名称,否则您只是放弃0.7000000000和"返回"来自InputList的免费List

在编译程序时你可能已经看到了这个错误:你的Prolog发行版​​可能会说出以下内容:

getItems/1

这意味着这两个变量在规则中只使用一次,因此可能是错误的。

答案 1 :(得分:1)

(a,b,c)不是Prolog中的列表。它是一个代表规范形式的术语:','(a,','(b,c))。列表[a,b,c]代表规范表单'.'(a,'.'(b,'.'(c,[])))(a,b,c)根本不会像列表一样,所以不会给你你想要的结果。

如果您希望将收藏集作为列表处理,请使用findall([A,B,C], item(A,B,C), M)

compareItem([H|T],L,[I|Out]):-
    writeln('-----------4-------------'),
    intersection(H,L,I),
    writeln('-----------5-------------'),
    compareItem(T,L,Out).
compareItem([],_,[]).

上面修复的原始谓词的另外两个问题是:

  1. 基本情况需要指示空列表[]是与空列表共同映射的结果。否则,Out永远不会被实例化。
  2. 您在递归中错放了I变量,因为它需要是结果中第3个参数的头部,而不是递归调用。
  3. 事实上,您可以使用maplist执行此任务:

    compareItem(M, L, Out) :-
        maplist(intersection(L), M, Out).
    

    这将缺少您的writeln来电。如果您愿意,可以添加一个:

    intersect_with_writeln(A, B, R) :-
        writeln('-----------4-----------'),
        intersect(A, B, R).
    
    compareItem(M, L, Out) :-
        maplist(intersect_with_writeln(L), M, Out).