如何在Prolog代码本身中编写“ findall”?

问题描述

因此,我对Prolog还是陌生的,我必须编写有关时间表的简短代码。 如何将findall函数添加代码本身?

happening(monday,chemistry).
happening(monday,english).
happening(tuesday,chemistry).
happening(wednesday,maths).
happening(friday,chemistry).
happening(friday,maths).

现在我想编写一个命令,显示一周内有多少次化学反应。

find_lessons(X) :-
findall(X,happening(X,chemistry),Bag).

解决方法

我假设您想要结果,所以Bag,因此您应该将find_lessons(X)重写为find_lessons(Bag)

find_lessons(Bag) :-
    findall(X,happening(X,chemistry),Bag).

这将提供化学课程的几天的列表,因此:

?- find_lessons(Bag).
Bag = [monday,tuesday,friday].

要计算课程数量,可以使用length/2

?- find_lessons(Bag),length(Bag,N).
Bag = [monday,friday],N = 3.

但是可以更有效地做到这一点。现在,在构建列表和计算元素方面存在开销。我们可以使用aggregate library [swi-doc]并使用aggregate/3 predicate [swi-doc]

?- aggregate(count,X^happening(X,Total).
Total = 3.

所以我们可以用以下方法计算化学课的数量:

:- use_module(library(aggregate))

num_chem_lessons(N) :-
    aggregate(count,N).