Question: I have a knowledge base that consists of students database in a file 'students.pl' like this:

```
% student(Name,Percent,List_of_Marks_in_3_subjects).
student('abc',83,[80,80,90]).
student('pqr',70,[70,60,80]).
student('xyz',76,[80,70,80]).

```

I want to access each student predicate from the knowledge base and calculate the average marks in each subject or average percentage, without using 'findall' or assert/retract.
I may want to use backtracking like this:

```
find_score_all(X) :- student(Name,Percent,L),
    write(Percent),nl,
    fail.
find_score_all(_).

```

With this approach I can access each element and write it, but if I want to add each 'Percent' value as an element to a list or just use a predicate like 'Percent1 is Total + Percent' to total the percent values and then find its average, how can I do so?
Note that I dont want to use findall or retract/assert and preferably find the average in one pass through the knowledge base since the knowledge base is very large.

Any help is appreciated.

Answer: 
```
%solution for sum of percents, you can replace with any other calculation sum_percent predicate.
listing(student/3, convert_to_list/2, sum_percent, sum_percent/2).

% student(Name,Percent,List_of_Marks_in_3_subjects).
student('abc',83,[80,80,90]).
student('pqr',70,[70,60,80]).
student('xyz',76,[80,70,80]).

convert_to_list(X, R):-
    student(N, P, LM),
    not(member(st(N, P, LM), X)),
    convert_to_list([st(N, P, LM)|X], R).

convert_to_list(X, X).

sum_percent:-
    convert_to_list([], X),
    sum_percent(X, S),
    write(S).

sum_percent([], 0).
sum_percent([st(_,E,_)|T], S):-
    sum_percent(T, S2),
    S is E+S2.

```
if you want to add to a list then you should use findall, or better, library([aggregate](http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%27A.1%27,swi%28%27/doc/Manual/aggregate.html%27%29%29)). But if you fear about efficiency, you could use something like this

```
integrate(ave, Goal, Ave) :-
    State = state(0, 0, _),
    repeat,
    (   call(Goal, V),
        arg(1, State, C), U is C+1, nb_setarg(1, State, U),
        arg(2, State, S), T is S+V, nb_setarg(2, State, T),
        fail
    ;   arg(1, State, C), arg(2, State, S), Ave is S/C
    ).

:- meta_predicate integrate(+, :, ?).

```

test:

```
members(X) :- member(X, [1,2,3,4]).

?- integrate(ave, members, R).
R = 2.5 .

```

Of course, you'll need to add error handling (at least, when counter `C == 0`).