`nb_setarg` used to get the max number - Reply 1

This is also available as aggregate_all/3 with max(), along with other “aggregation operators on backtrackable predicates”.

aggregate_all(max(X), p(X), Max)

The implementation is quite close to yours:

aggregate_all(max(X), Goal, Max) :-
    !,
    State = state(X),
    (  call(Goal),
           arg(1, State, M0),
           M is max(M0,X),
           nb_setarg(1, State, M),
           fail
    ;  arg(1, State, Max),
           nonvar(Max)
    ).

The library is relatively new and very useful.

2 Likes

Thank you. The similarity was a suprising for me. I kept a feeling
about my destructive structure flag(_) as something like a blackboard living in the predicate p/1, which is analogous to a file-control- block (dead terminology ?). It should be hidden from the user in the ultimate, but I like it for some reason which I can’t explain well.

The destructive assignment is necessary one way or another. I guess findall must do something very similar; just in this max() case it is proper aggregation and you really don’t need to materialize the full list. Your solution as well as the library implementation are still much better than using the database through assert and retract: the “black board” is strictly local to the aggregation predicate. I’d say it is indeed hidden from the user well enough?

I was glad to see this phrase because it is exactly what I tried to find to say, in particular, “hidden from the user well enough”. As far as I remember it is my first time to observe such fuzzy but creative criteria. I will keep “hidden from the user well enough” in mind as a fresh prolog programming principle.

Richard O’Keefe has a chapter in The Craft of Prolog on “all solutions” predicates and the tricky edge cases.

I happened to have a copy of the book, but havn’t opened it yet. In the index, nb_setarg/3 is not there, but so is findall/3. It may take some time for me to understand the

[quote=“peter.ludemann, post:5, topic:5604”]
the tricky edge cases.
[/quote] If some kind of general schema for computing aggregation is proposed or discussed in the chapter, it is interesting also for me. But I am not sure, and it may take some time for me to digest it.

nb_setarg/3 is a SWI-Prolog innovation. I think that there was something similar in Quintus Prolog. But O’Keefe tries to avoid solutions that only work on somme Prolog implementations.

Yes, I bothered to look through the last chapter of The Craft of Prolog and it more or less dances around the problem. It explains why using assert and retract for implementing bagof/setof is buggy; it suggests using the “recorded database” available in most Prologs of the time (SWI-Prolog also has it); it then discusses the semantics of bagof/setof/findall and possible alternatives. Finally, it does mention some “aggregate” library predicates available in Quintus and NU Prolog without explaining how they could have been implemented (so probably they were not implemented in Prolog!), and suggests implementing those in Prolog as an exercise, using setof/3.

My take-away is that nb_setarg/3 does provide a mechanism for implementing aggregation that has superseded what was available at the time when The Craft of Prolog was written.