# \`nb\_setarg\` used to get the max number - Reply 1

**URL:** <https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604>\
**Category:** General\
**Created:** [July 12, 2022, 6:52am UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604 "2022-07-12T06:52:51Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [July 12, 2022, 6:52am UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/1 "2022-07-12T06:52:51Z")

</div>

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

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

```

[The implementation](https://github.com/SWI-Prolog/swipl-devel/blob/158daf8212a825c7f7dd983150ba30e46a27330f/library/aggregate.pl#L197-L207) is quite close to yours:

```prolog
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.

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [July 12, 2022, 8:01am UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/2 "2022-07-12T08:01:16Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [July 12, 2022, 10:24am UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/3 "2022-07-12T10:24:27Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [July 12, 2022, 11:57am UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/4 "2022-07-12T11:57:45Z")

</div>

> [@Boris](#):
>
> 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.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 12, 2022, 4:55pm UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/5 "2022-07-12T16:55:15Z")

</div>

> [@kuniaki.mukai](#):
>
> hidden from the user well enough

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

---

<div class="post-metadata">

**Author:** ![kuniaki.mukai](https://avatars.discourse-cdn.com/v4/letter/k/c67d28/32.png) [@kuniaki.mukai](https://swi-prolog.discourse.group/u/kuniaki.mukai)\
**Post date:** [July 12, 2022, 6:24pm UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/6 "2022-07-12T18:24:01Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [July 12, 2022, 7:17pm UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/7 "2022-07-12T19:17:33Z")

</div>

> [@kuniaki.mukai](#):
>
> `nb_setarg/3` is not [in _The Craft of Prolog_

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.

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [July 12, 2022, 7:31pm UTC](https://swi-prolog.discourse.group/t/nb-setarg-used-to-get-the-max-number-reply-1/5604/8 "2022-07-12T19:31:14Z")

</div>

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.
