# Proposal: Why not add assertion/2?

**URL:** <https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697>\
**Category:** Request For Comments\
**Tags:** discussion\
**Created:** [July 26, 2020, 5:10pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697 "2020-07-26T17:10:43Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dtonhofer](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/dtonhofer/32/902_2.png) [@dtonhofer](https://swi-prolog.discourse.group/u/dtonhofer)\
**Post date:** [July 26, 2020, 5:10pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/1 "2020-07-26T17:10:43Z")

</div>

Currently we only have assertion/1 from [`library(debug)`](https://eu.swi-prolog.org/pldoc/man?section=debug) described as

`assertion(:Goal)`

which throws an exception with a (non-ISO standard) formal term `assertion_error/2` if the `Goal` fails.

In fact, the exception thrown in case of `Goal` equal to `false` is

`error(assertion_error(fail,user:false),_4750)`

This is similar to Java’s [`assert(expr)`](https://docs.oracle.com/javase/specs/jls/se14/html/jls-14.html#jls-14.10) (first added in Java 1.4 in 2002 only btw.)

I suppose `assertion/1` can be compiled-out using expand\_goal/2, if the `Goal` is too expensive at runtime; I haven’t tried that yet.

* * *

It would be useful to have an `assertion/2` described as:

`assertion(:Goal,:Closure)`

where `Closure` is executed when `Goal` fails with one additional uninstantiated argument, which shall be instantiated by the Closure, and which inserted into the second argument (the context term) of the `error/2` term:

`error(assertion_error(fail,user:false),T)`

Then one could generate good error messages, similar to Java’s `assert(expr,msg)`:

**Example:**

Call point:

```prolog
assertion(X<Y,assertion_handler(X,Y)).

```

And handler:

```prolog
assertion_handler(X,Y,T) :- 
   with_output_to(string(T),format("This is bad. ~q < ~q; this rocket's gonna crash!!",[X,Y])).

```

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 26, 2020, 5:25pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/2 "2020-07-26T17:25:29Z")

</div>

Why not use a predicate with two clauses?

See recent post: [How to identify if a predicate is a DCG?](https://swi-prolog.discourse.group/t/how-to-identify-if-a-predicate-is-a-dcg/2696)

```prolog
build_export(M,Exports) :-
    current_module(M), !,
    setof(Predicate_indicator,local_predicate_generator(M:Predicate_indicator),Exports).
build_export(M,_) :-
    format(string(Lines),'Module `~w'' not loaded.~nPlease use consult/1 or use_module/1 to load the module.~n',[M]),
    print_message_lines(user_error,kind(error),[Lines]).

```

---

<div class="post-metadata">

**Author:** ![dtonhofer](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/dtonhofer/32/902_2.png) [@dtonhofer](https://swi-prolog.discourse.group/u/dtonhofer)\
**Post date:** [July 26, 2020, 5:29pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/3 "2020-07-26T17:29:14Z")

</div>

> Why not use a predicate with two clauses?

Ah, but this wouldn’t help me in getting the informative term I’m generating in the Closure into the exception term, which is thrown by `assertion/1`. The idea is to have the information in the exception, not on STDERR. Besides, the assertion/1 call can appear anywhere inside a clause, maybe multiple times.

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 26, 2020, 5:39pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/4 "2020-07-26T17:39:23Z")

</div>

Then why not pass an accumulator around to hold the state for the error messages? You could then use DCGs? No?

---

<div class="post-metadata">

**Author:** ![dtonhofer](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/dtonhofer/32/902_2.png) [@dtonhofer](https://swi-prolog.discourse.group/u/dtonhofer)\
**Post date:** [July 26, 2020, 5:46pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/5 "2020-07-26T17:46:14Z")

</div>

Not an accumulator. Just terms that are of interest to the error-text generating closure. There may be no arguments at all:

```prolog
assertion(X<Y,=("The usual Sunday evening exception")).

```

Ok, I don’t know whether that would work and it’s also somewhat ugly, but the idea is to unify the term T that will be transported by the exception term with a constant message, so the following is thrown:

`error(assertion_error(fail,user:(2<1),"The usual Sunday evening exception")`

With assertion/1 one just gets

`error(assertion_error(fail,user:(2<1)),_)`

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 26, 2020, 6:04pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/6 "2020-07-26T18:04:43Z")

</div>

My understanding of assertions, regardless of programming language, is that during development they are there to check that you are meeting certain requirements, typically on entry and exit of a procedure. They are not there to do the heavy lifting and are typically a predicate, regardless of programming language, to signal the condition is valid.

When the code reaches a production level they are typically removed; the condition for being considered production code is the optimize option. SWI-Prolog does the same with [debug/3](https://www.swi-prolog.org/pldoc/man?section=debug).

If you want detailed error messages then I would suggest you look for other means. 😀

---

<div class="post-metadata">

**Author:** ![dtonhofer](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/dtonhofer/32/902_2.png) [@dtonhofer](https://swi-prolog.discourse.group/u/dtonhofer)\
**Post date:** [July 26, 2020, 7:10pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/7 "2020-07-26T19:10:38Z")

</div>

Well, you would really use them to check internal invariants too and I always recommend to leave assertions on unless they are costly, but yeah.

> **[Assertion (software development)](https://en.wikipedia.org/wiki/Assertion_(software_development))**
>
> In computer programming, specifically when using the imperative programming paradigm, an assertion is a predicate (a Boolean-valued function over the state space, usually expressed as a logical proposition using the variables of a program) connected to a point in the program, that always should evaluate to true at that point in code execution. Assertions can help a programmer read the code, help a compiler compile it, or help the program detect its own defects.
> For the latter, some programs chec...

Take a look at the Power Assertions in Groovy:

[http://docs.groovy-lang.org/next/html/documentation/core-testing-guide.html](http://docs.groovy-lang.org/next/html/documentation/core-testing-guide.html)

```prolog
def x = [1,2,3,4,5]
assert (x << 6) == [6,7,8,9,10]

// Output:
//
// Assertion failed:
// assert (x << 6) == [6,7,8,9,10]
// | | |
// | | false
// | [1, 2, 3, 4, 5, 6]
// [1, 2, 3, 4, 5, 6]

```

Probably going too far.

Still, adding a generated message if there is failure of the assertion predicate is not “heavy lifting”. It’s just adding a message? Let’s see if I can code that.

Here’s how Ciao Prolog does it:

[https://ciao-lang.org/ciao/build/doc/ciao.html/assertions\_doc.html](https://ciao-lang.org/ciao/build/doc/ciao.html/assertions_doc.html)

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [July 26, 2020, 11:04pm UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/8 "2020-07-26T23:04:33Z")

</div>

Have you looked for or seen:  
Package [assertions](https://www.swi-prolog.org/pack/list?p=assertions) - Ciao Assertions Reader for SWI-Prolog  
Package [ciao](https://www.swi-prolog.org/pack/list?p=ciao) - Ciao Prolog compatibility library  
Package [dialect-ciao](https://www.swi-prolog.org/pack/list?p=dialect-ciao) - Ciao Prolog compatibility library

I have not done anything more with them than read the description and note it here.

Some of the authors are  
@edison  
@jromme

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [July 27, 2020, 7:52am UTC](https://swi-prolog.discourse.group/t/proposal-why-not-add-assertion-2/2697/9 "2020-07-27T07:52:53Z")

</div>

Two remarks. Ciao assertions are very different from SWI-Prolog assertions. They merely share the name. SWI-Prolog assertion/1 is modeled after C assert/1, while Ciao are declarations about the behavior of a predicate (types, pre- and post conditions and some more). Ciao conditions were originally mostly intended for static analysis. @edison started? using them to insert runtime checks. I may be a little off, so please correct where I’m wrong 🙂

As for SWI-Prolog’s assertion/1, its behavior can be changed at various levels: the _hook_ prolog:assertion\_failed/2 can be used to define what happens. The default is an exception which you catch or for which you can change the way it is printed. I think that is enough.
