我目前有一个数据库,其中包含一个人员列表,他们发送邮件的人以及邮件发送的日期。请参阅以下内容:
message(allan, steve, 2013-09-03).
message(nayna, jane, 2013-09-03).
message(steve, jane, 2013-09-04).
message(steve, allan, 2013-09-04).
message(mark, martin, 2013-09-04).
message(martin, steve, 2013-09-04).
message(allan, martin, 2013-09-05).
对于我的一个任务,我需要创建一个规则,该规则返回人1(P1)和人2(P2)交换消息的所有日期的列表,直到日期(D)。
到目前为止,我有以下内容:
message(P1,P2,Date),D=Date,print([D]); message(P2,P1,Date),D=Date,print([D]).
我需要一条规则,只返回所有日期的列表,而不必每次都输入;
。
我知道这条规则需要修复,所以我们非常感谢任何帮助/建议!
答案 0 :(得分:1)
您可能希望显示的代码是您规则的主体,
my_rule(P1,P2,D):-
message(P1,P2,Date),D=Date,print([D]); message(P2,P1,Date),D=Date,print([D]).
当然,对于之前的日期,我们需要@<
代替=
:
my_rule(P1,P2,D):-
message(P1,P2,Date),D@<Date,print([D]); message(P2,P1,Date),D@<Date,print([D]).
但那里有很多代码复制;我们需要抽象出某些东西,显然:
my_rule(P1,P2,D):-
message_between(P1,P2,Date),D@<Date,print([D]).
message_between(P1,P2,Date):- message(P1,P2,Date) ; message(P2,P1,Date).
此代码仍有错误。哪个日期给我们?我们找到哪个日期?我们要打印出哪个?
my_rule(P1,P2,D):-
message_between(P1,P2,Date),D @>= Date,print([Date]).
这是对的。现在我们可以进入问题的第二部分 - 您不希望一直“按;
”,逐一获得解决方案。
首先,请注意,您现在不会从谓词获取解决方案,而是由它打印。修复:
my_rule(P1,P2,Dtop,Date):-
message_between(P1,P2,Date),Dtop @>= Date.
现在,当my_rule/4
成功时,它将第四个参数实例化为两个给定人之间的消息交换日期,如果它不晚于Dtop
date(第三个参数)。
要全部收集它们,您需要使用内置谓词setof
,正如mbratch在评论中向您暗示的那样。
all_dates(P1,P2,Dtop,DatesList):-
setof( Date, my_rule(P1,P2,Dtop,Date), .... ).
如果谓词all_dates
的所有三个第一个参数都被完全给定(即被实例化为基础术语),则它将起作用。用有意义的条目替换点。要么猜测,要么 - 更好 - 阅读setof
和findall
的文档。
这里仍存在一个差异。如果在给定的人和日期组合中根本没有交换消息怎么办?上面给出的规则将失败。也许您希望以空列表作为解决方案来取得成功。你能做出必要的调整吗?使用以下骨架:
rule_suceeds( ..., DatesList):-
/*... a rule that instantiates `DatesList` ...*/ -> true ; ... = [] .