Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

R6RS: assertion-violation vs. assert

188 views
Skip to first unread message

Grant Rettke

unread,
Feb 15, 2009, 11:55:33 AM2/15/09
to
In R6RS, both assertion-violation and assert are available for use.

"The assertion-violation procedure should be called when an invalid
call to a procedure was made, either passing an invalid number of
arguments, or passing an argument that it is not specified to handle."

I take it that "assert" is left for everything else; in particular to
help the procedure implemeter verify that the procedure, his
implementation of it, is behaving as expected?

leppie

unread,
Feb 15, 2009, 1:06:12 PM2/15/09
to

assert is a macro in R6RS, basically:

(define-syntax assert
(syntax-rules ()
[(_ expr)
(unless expr
(assertion-violation #f "assertion failed"))]))

Cheers

leppie

Grant Rettke

unread,
Feb 15, 2009, 4:33:51 PM2/15/09
to
On Feb 15, 12:06 pm, leppie <xacc....@gmail.com> wrote:
> assert is a macro in R6RS, basically:

When are you likely to use it?

Derick Eddington

unread,
Feb 15, 2009, 10:01:21 PM2/15/09
to
On Feb 15, 10:06 am, leppie <xacc....@gmail.com> wrote:
> assert is a macro in R6RS, basically:
>
> (define-syntax assert
>   (syntax-rules ()
>     [(_ expr)
>       (unless expr
>         (assertion-violation #f "assertion failed"))]))

Actually, R6RS says it must return the value of expr if it's not #F:

(define-syntax assert
(syntax-rules ()
((_ expr)
(let ((x expr))
(if x x (assertion-violation #F ---))))))

Ikarus and Larceny do not, Ypsilon does, didn't check others.

R6RS does not say what assert should do if expr returns a number of
values other than 1, but maybe what it should do is implied by another
part of the report?

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Feb 15, 2009, 10:43:12 PM2/15/09
to

assertion-violation is a convenient way to add &who, &message, and
&irritants conditions to the exception. It should be used for failed
checks of arguments or other user mistakes to give consistent and
portable exceptions.

I believe assert was intended to be useful for checking internal
invariants / assumptions, similar to how C's assert is used, and this
is why "Implementations should exploit the fact that assert is syntax
to provide as much information as possible about the location of the
assertion failure." but this information is implementation-dependent.
I think using assert to check your assumptions is good, and I use it
when I'm not certain my assumptions are correct or to indicate non-
obvious assumptions. I don't understand why it's in the report the
way it is. I would think it should always return unspecified values
and should be specified that it may not be evaluated (e.g., turned off
via a compiler / interpreter option, similar to C's #define NDEBUG).

--
: Derick
----------------------------------------------------------------

Andrew Reilly

unread,
Feb 15, 2009, 11:06:52 PM2/15/09
to
On Sun, 15 Feb 2009 19:43:12 -0800, Derick Eddington wrote:

> should be specified that it may not be evaluated (e.g., turned off via a
> compiler / interpreter option, similar to C's #define NDEBUG).

Do any r6rs compilers provide that feature? (an assertions-off
compilation mode) I'd appreciate it. I suppose that one could do it
oneself by arranging to redefine assert as values for the compilation.

Cheers,

--
Andrew

leppie

unread,
Feb 15, 2009, 11:34:07 PM2/15/09
to
On Feb 16, 6:06 am, Andrew Reilly <andrew-newsp...@areilly.bpc-

No, but it is easily enough defined. An example can be seen in the
psyntax sources in the (psyntax config) library.

Also, you cant redefine assert, unless you import another definition
from another library, in all the libraries used.

Cheers

leppie

leppie

unread,
Feb 15, 2009, 11:35:05 PM2/15/09
to
On Feb 16, 5:43 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

>  I would think it should always return unspecified values

I agree with that.

Cheers

leppie

Michael Sperber

unread,
Feb 16, 2009, 2:36:58 AM2/16/09
to

Grant Rettke <gre...@gmail.com> writes:

> I take it that "assert" is left for everything else; in particular to
> help the procedure implemeter verify that the procedure, his
> implementation of it, is behaving as expected?

Note the note:

>> Implementations should exploit the fact that `assert' is syntax to
>> provide as much information as possible about the location of the
>> assertion failure.

In particular, it may be difficult for `assertion-violation' to provide
the same level of detail about the failure as it's a procedure, and the
call to it may be a tail call. (In fact, it often is.)

--
Cheers =8-} Mike
Friede, Völkerverständigung und überhaupt blabla

Grant Rettke

unread,
Feb 16, 2009, 11:59:48 AM2/16/09
to
On Feb 16, 1:36 am, Michael Sperber <sper...@deinprogramm.de> wrote:

> Grant Rettke <gret...@gmail.com> writes:
> > I take it that "assert" is left for everything else; in particular to
> > help the procedure implemeter verify that the procedure, his
> > implementation of it, is behaving as expected?
>
> Note the note:
>
> >>  Implementations should exploit the fact that `assert' is syntax to
> >>  provide as much information as possible about the location of the
> >>  assertion failure.
>
> In particular, it may be difficult for `assertion-violation' to provide
> the same level of detail about the failure as it's a procedure, and the
> call to it may be a tail call.  (In fact, it often is.)

assertion-violation will provide more consistent, portable messages;
but assert will be in a better position to easily expose more details.
That sounds like tension!

Which one of these would be the best thing for reporting erroneous
utilization of macros? I mean something like "This macro expects at
least 2 operands that are the day and week..." or something.

Michele Simionato

unread,
Feb 16, 2009, 1:20:40 PM2/16/09
to
On Feb 16, 5:59 pm, Grant Rettke <gret...@gmail.com> wrote:
> assertion-violation will provide more consistent, portable messages;
> but assert will be in a better position to easily expose more details.
> That sounds like tension!
>
> Which one of these would be the best thing for reporting erroneous
> utilization of macros? I mean something like "This macro expects at
> least 2 operands that are the day and week..." or something.

I would say a third one: syntax-violation

Grant Rettke

unread,
Feb 16, 2009, 2:35:54 PM2/16/09
to
On Feb 16, 12:20 pm, Michele Simionato <michele.simion...@gmail.com>
wrote:

> I would say a third one: syntax-violation

Right, duh, thanks Michele; I even had that one in my notes! :)

kub

unread,
Feb 16, 2009, 4:32:31 PM2/16/09
to
<snip>

> Which one of these would be the best thing for reporting erroneous
> utilization of macros? I mean something like "This macro expects at
> least 2 operands that are the day and week..." or something.

What about syntax-violation ?

--
Bogdan

kub

unread,
Feb 16, 2009, 5:00:52 PM2/16/09
to
On Feb 16, 5:43 am, Derick Eddington <derick.edding...@gmail.com>
<snip>

> I would think it should always return unspecified values
> and should be specified that it may not be evaluated (e.g., turned off
> via a compiler / interpreter option, similar to C's #define NDEBUG).

R6RS says that :
1. assert emits &assertion condition
and
2.
"...
(define-condition-type &assertion &violation
make-assertion-violation assertion-violation?)

This type describes an invalid call to a procedure, either passing an
invalid number of arguments, or passing an argument of the wrong
type.
..."

1&2 It mean that 'assert is about procedure call safety or in other
words about procedure pre-condition check.
If you want to turn-off this safety for all procedures than I have
following questions regarding mode with assert turned-off:
1. What about procedures accepting input from users ? Should they
behave unsafe ?
2. What about standard procedures ? Do you want to turn-off safety
for them as well ? Or they should use different assertion mechanism ?
3. If assert is associated with debug configuration then which
mechanism should be used to implement checks for release
configuration ?

--
Bogdan

Derick Eddington

unread,
Feb 17, 2009, 1:21:17 AM2/17/09
to
On Feb 16, 2:00 pm, kub <wareverboh...@gmail.com> wrote:
> On Feb 16, 5:43 am, Derick Eddington <derick.edding...@gmail.com>
> <snip>
>
> > I would think it should always return unspecified values
> > and should be specified that it may not be evaluated (e.g., turned off
> > via a compiler / interpreter option, similar to C's #define NDEBUG).
>
> R6RS says that :
> 1. assert emits &assertion condition
> and
> 2.
> "...
> (define-condition-type &assertion &violation
> make-assertion-violation assertion-violation?)
>
> This type describes an invalid call to a procedure, either passing an
> invalid number of arguments, or passing an argument of the wrong
> type.
> ..."
>
> 1&2 It mean that 'assert is about procedure call safety or in other
> words about procedure pre-condition check.

If that's all &assertion is for, why doesn't the specification of
assert say that's all assert should be used for? and why are they
named "assertion" and "assert" if they're not to be used for all types
of assertions? I think exceptions with &assertion make sense for
argument checking because you're asserting what must be true, but if
R6RS's intent was to have a condition type and other facilities only
for argument checking then the name should not be "assertion" and that
intent should have clearly and consistently been made.

> If you want to turn-off this safety for all procedures than I have
> following questions regarding mode with assert turned-off:
> 1. What about procedures accepting input from users ? Should they
> behave unsafe ?
> 2. What about standard procedures ? Do you want to turn-off safety
> for them as well ? Or they should use different assertion mechanism ?
> 3. If assert is associated with debug configuration then which
> mechanism should be used to implement checks for release
> configuration ?

I'm not suggesting turning off debug mode should turn off argument
checks or other checks required to make high-level safe languages and
libraries. I want consistent portable exceptions for required
checks. I think exceptions should be able to be used portably
programmatically and not just for the base exception handler to print
messages for humans. An assert with implementation-specific semantics
for what the exceptions it raises are, used for required checks, is
not robust for portable programmatic purposes, IMO. Why is an
implementation-specific assert in a standard that is supposed to be
about portability?

Also, I question whether assert, with any semantics, should even be in
the standard. With compatibility libraries, implementations can
provide their things that tell file name, line number, etc. and
library / framework writers can make a consistent portable assert that
uses them to achieve whatever qualities users might want and we can
have different competing asserts for different uses and users.

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Feb 17, 2009, 1:32:21 AM2/17/09
to
On Feb 15, 11:36 pm, Michael Sperber <sper...@deinprogramm.de> wrote:

> Grant Rettke <gret...@gmail.com> writes:
> > I take it that "assert" is left for everything else; in particular to
> > help the procedure implemeter verify that the procedure, his
> > implementation of it, is behaving as expected?
>
> Note the note:
>
> >> Implementations should exploit the fact that `assert' is syntax to
> >> provide as much information as possible about the location of the
> >> assertion failure.
>
> In particular, it may be difficult for `assertion-violation' to provide
> the same level of detail about the failure as it's a procedure, and the
> call to it may be a tail call. (In fact, it often is.)

When and why would a call to assertion-violation or assert be a tail
call? Please point us to somewhere we can see that this has been done
often or give us an example that shows why it would be done often.

Thanks,

--
: Derick
----------------------------------------------------------------

Michael Sperber

unread,
Feb 17, 2009, 2:20:08 AM2/17/09
to

Derick Eddington <derick.e...@gmail.com> writes:

> When and why would a call to assertion-violation or assert be a tail
> call? Please point us to somewhere we can see that this has been done
> often or give us an example that shows why it would be done often.

This is a fairly common pattern:

(define (proc arg)
(if (ok? arg)
(compute arg)
(assertion-violation 'proc "arg not ok" arg")))

Derick Eddington

unread,
Feb 17, 2009, 4:59:02 AM2/17/09
to
On Feb 16, 11:20 pm, Michael Sperber <sper...@deinprogramm.de> wrote:

> Derick Eddington <derick.edding...@gmail.com> writes:
> > When and why would a call to assertion-violation or assert be a tail
> > call?  Please point us to somewhere we can see that this has been done
> > often or give us an example that shows why it would be done often.
>
> This is a fairly common pattern:
>
> (define (proc arg)
>   (if (ok? arg)
>       (compute arg)
>       (assertion-violation 'proc "arg not ok" arg")))

Right, but assertion-violation never returns so I don't find this case
justifying. I mentioned "assertion-violation or assert" because you
mentioned only assertion-violation and I wasn't sure what you meant.
What's an example, of a case that would occur often, of assert being
in tail position where its return value would actually be used?

Thanks,

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Feb 17, 2009, 5:10:20 AM2/17/09
to
On Feb 17, 1:59 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

> What's an example, of a case that would occur often, of assert being
> in tail position where its return value would actually be used?

Also, what's a realistic example in which the return value of assert
would be used in any type of case (not necessarily the tail position
case)?

--
: Derick
----------------------------------------------------------------

leppie

unread,
Feb 17, 2009, 5:53:22 AM2/17/09
to
On Feb 17, 11:59 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

> On Feb 16, 11:20 pm, Michael Sperber <sper...@deinprogramm.de> wrote:
>
> > Derick Eddington <derick.edding...@gmail.com> writes:
> > > When and why would a call to assertion-violation or assert be a tail
> > > call?  Please point us to somewhere we can see that this has been done
> > > often or give us an example that shows why it would be done often.
>
> > This is a fairly common pattern:
>
> > (define (proc arg)
> >   (if (ok? arg)
> >       (compute arg)
> >       (assertion-violation 'proc "arg not ok" arg")))
>
> Right, but assertion-violation never returns so I don't find this case
> justifying.

It is still called, and by the time it escapes somewhere else, the
previous stack frame is gone!

If it doesn't, the Scheme is not doing proper tail recursion :)

Cheers

leppie

leppie

unread,
Feb 17, 2009, 5:57:42 AM2/17/09
to
On Feb 17, 12:10 pm, Derick Eddington <derick.edding...@gmail.com>
wrote:

> Also, what's a realistic example in which the return value of assert
> would be used in any type of case (not necessarily the tail position
> case)?

(define (lookup ht key)
(hashtable-ref (assert (and (hashtable? ht) ht)) key #f))

OK, maybe not realistic, but rather why I feel it should not return a
specified value(s).

I would even argue that the assert macro should be a dummy definition,
allowing it to be used before other definitions, else you end up with:

(define (foo bar)
(assert (bar? bar))
(let ()
(define baz 10)
...))

Cheers

leppie

kub

unread,
Feb 17, 2009, 6:53:24 AM2/17/09
to
On Feb 17, 12:57 pm, leppie <xacc....@gmail.com> wrote:
<snip>

> I would even argue that the assert macro should be a dummy definition,
> allowing it to be used before other definitions, else you end up with:
>
> (define (foo bar)
>   (assert (bar? bar))
>   (let ()
>     (define baz 10)
>     ...))

This is good programming style, even more I'd like to have contract
library which allows me to do:

(define/c (foo (bar : bar?) ) : foo-result?
...)

This style allows me to have some documenting tool which can capture
procedures signature.

But! There are exceptions to your suggestion. As stated in R6RS
"5.4. Argument checking" there are situations when full check of
arguments can be expensive. And in this case you will need assert or
something like this to check *part* of argument only on when this
part is really involved in evaluation.

--
Bogdan

kub

unread,
Feb 17, 2009, 7:41:06 AM2/17/09
to
On Feb 17, 8:21 am, Derick Eddington <derick.edding...@gmail.com>
wrote:
<snip>

> If that's all &assertion is for, why doesn't the specification of
> assert say that's all assert should be used for?

It can be logically concluded from the fact that it raises &assertion
condition which in turn describes invalid arguments.


> and why are they
> named "assertion" and "assert" if they're not to be used for all types
> of assertions?  

It is not question to me, this is what r6rs says.
But in many situations particular programming language terms have more
semantics than equivalent English terms or general CS terms. And in
this case both assert and &assertion mean only procedure argument
checks.

> I think exceptions with &assertion make sense for
> argument checking because you're asserting what must be true, but if
> R6RS's intent was to have a condition type and other facilities only
> for argument checking then the name should not be "assertion" and that
> intent should have clearly and consistently been made.

Completely agree with you. invalid-argument, missing-argument ... etc.
names should be much more readable then assert/assertion.
Also those identifiers can be improved if using contracts terminology
which splits all asserts (not only argument checking) into 4
categories:
1. pre-condition / require
2. post-conditions / ensure
3. invariant checks
4. debug assertions (turned off in release).
In most cases debug assertions should terminate program
execution providing as much information to developer as possible
and alternative to terminating program can suggest to activate
debugger-tool.

>
> I'm not suggesting turning off debug mode should turn off argument
> checks or other checks required to make high-level safe languages and
> libraries.  I want consistent portable exceptions for required
> checks.  I think exceptions should be able to be used portably
> programmatically and not just for the base exception handler to print
> messages for humans.
>  An assert with implementation-specific semantics
> for what the exceptions it raises are, used for required checks, is
> not robust for portable programmatic purposes, IMO.  Why is an
> implementation-specific assert in a standard that is supposed to be
> about portability?

The only implementation-dependent part of assert is message in
message-condition, right? In this case I see no problem with
portability, do you?

> Also, I question whether assert, with any semantics, should even be in
> the standard.  

I think assert form is accidentally :) borrowed from c/c++ where it
has semantics of mentioned debug assertion and again accidentally it
was puzzled with pre-conditions idea.

> With compatibility libraries, implementations can
> provide their things that tell file name, line number, etc.

100% agree. It is the most annoying thing about assert.

> and
> library / framework writers can make a consistent portable assert that
> uses them to achieve whatever qualities users might want and we can
> have different competing asserts for different uses and users.

--
Bogdan

Sam TH

unread,
Feb 17, 2009, 8:39:38 AM2/17/09
to
On Feb 17, 6:53 am, kub <wareverboh...@gmail.com> wrote:
> On Feb 17, 12:57 pm, leppie <xacc....@gmail.com> wrote:
> <snip>
>
> > I would even argue that the assert macro should be a dummy definition,
> > allowing it to be used before other definitions, else you end up with:
>
> > (define (foo bar)
> >   (assert (bar? bar))
> >   (let ()
> >     (define baz 10)
> >     ...))
>
> This is good programming style, even more I'd like to have contract
> library which allows me to do:
>
>  (define/c (foo (bar : bar?) ) : foo-result?
>       ...)
>
> This style allows me to have some documenting tool which can capture
> procedures signature.

It's not exactly what you've asked for, but you should definitely look
at the PLT Scheme contract library:
http://docs.plt-scheme.org/guide/contracts.html

sam th

leppie

unread,
Feb 17, 2009, 10:30:11 AM2/17/09
to
On Feb 17, 3:39 pm, Sam TH <sam...@gmail.com> wrote:

> It's not exactly what you've asked for, but you should definitely look
> at the PLT Scheme contract library:
>  http://docs.plt-scheme.org/guide/contracts.html
>
> sam th

While we are pimping libraries :)

https://ironscheme.svn.codeplex.com/svn/IronScheme/IronSchemeConsole/ironscheme/contracts.ss
https://ironscheme.svn.codeplex.com/svn/IronScheme/IronSchemeConsole/ironscheme/contracts-helper.ss

The only part that is non-R6RS is string-split as I like to make my
parameters like: foo:bar where foo is the name, bar is the 'type' that
supplies the bar? predicate. So bar is the predicate less the ? (I
know its a bit limiting due to enforcing the '?' but it looks a lot
better than foo:bar? :)

Cheers

leppie

kub

unread,
Feb 17, 2009, 11:49:19 AM2/17/09
to
On Feb 17, 3:39 pm, Sam TH <sam...@gmail.com> wrote:
> It's not exactly what you've asked for, but you should definitely look
> at the PLT Scheme contract library:
>  http://docs.plt-scheme.org/guide/contracts.html

Guess where did I get this idea :)

Seriously, I wrote my own R6RS contract library somewhat similar to
PLT. Difference is that my library can emit detailed human-readable
messages describing failure. Even for very complicated constraints.

What is wrong with my library is performance. Despite very clean and
simple procedure based implementation, it is about 200-300 times
slower (for PLT compiled executable) than dumb assert expression. I
already have macros&monads based implementation which is only 10-20
slower than assert equivalent. But I have reasons to think that
performance for most cases can be close to the assert equivalent.

I would appreciate if you can suggest any sources/articles describing
contracts/constraints implementations in scheme. Including PLT one
which I was not able to grok from sources because of complexity.

--
Bogdan

kub

unread,
Feb 17, 2009, 12:06:53 PM2/17/09
to
On Feb 17, 5:30 pm, leppie <xacc....@gmail.com> wrote:
<snip>
> While we are pimping libraries  :)
>
> https://ironscheme.svn.codeplex.com/svn/IronScheme/IronSchemeConsole/...https://ironscheme.svn.codeplex.com/svn/IronScheme/IronSchemeConsole/...

Looks like we all are spinning around the same ideas :)
Since contract library is needed anyway for r6rs wouldn't it
be better to join our efforts ?

> The only part that is non-R6RS is string-split as I like to make my
> parameters like: foo:bar where foo is the name, bar is the 'type' that

I do not feel that joining argument identifier and argument type
predicate is a good idea. It couldn't solve contracts problem
since argument contracts can be (and in many cases are) much more
complicated than dumb predicate check. Please correct me if i did
understand your implementation incorrectly.

For details please look at various PLT contract combinators (like or/
c) and their role for PLT documentation. Besides there are exceptions/
conditions which are part of contract as well (I saw nothing in PLT on
this).

Grant Rettke

unread,
Feb 17, 2009, 12:47:45 PM2/17/09
to
On Feb 17, 7:39 am, Sam TH <sam...@gmail.com> wrote:
> It's not exactly what you've asked for, but you should definitely look
> at the PLT Scheme contract library:
>  http://docs.plt-scheme.org/guide/contracts.html

How miuch would a R6RS port of it cost? :)

Sam TH

unread,
Feb 17, 2009, 12:51:17 PM2/17/09
to
On Feb 17, 11:49 am, kub <wareverboh...@gmail.com> wrote:
> On Feb 17, 3:39 pm, Sam TH <sam...@gmail.com> wrote:
>
> > It's not exactly what you've asked for, but you should definitely look
> > at the PLT Scheme contract library:
> >  http://docs.plt-scheme.org/guide/contracts.html
>
> Guess where did I get this idea :)
>
> Seriously, I wrote my own R6RS contract library somewhat similar to
> PLT. Difference is that my library can emit detailed human-readable
> messages describing failure. Even for very complicated constraints.

I'm not sure what you mean here. The PLT contract system provides
human-readable error messages, like this:

'n broke the contract (-> number? number?) on x; expected <number?>,
given: #f

(program at the end of this message)

>
>   What is wrong with my library is performance. Despite very clean and
> simple procedure based implementation, it is about 200-300 times
> slower (for PLT compiled executable) than dumb assert expression. I
> already have macros&monads based implementation which is only 10-20
> slower than assert equivalent. But I have reasons to think that
> performance for most cases can be close to the assert equivalent.
>
> I would appreciate if you can suggest any sources/articles describing
> contracts/constraints implementations in scheme. Including PLT one
> which I was not able to grok from sources because of complexity.

There are a number of papers on the PLT Contract system. You should
look here:

http://www.ece.northwestern.edu/~robby/pubs/

and click on 'Contracts' on the left-hand side to narrow it down to
just the contract papers.

sam th

Program:


(module m scheme

(define (x a) 1)
(provide/contract [x (number? . -> . number?)]))

(module n scheme
(require 'm)
(x #f))

(require 'n)

Grant Rettke

unread,
Feb 17, 2009, 1:19:39 PM2/17/09
to
On Feb 17, 11:51 am, Sam TH <sam...@gmail.com> wrote:
> (module m scheme
>
>   (define (x a) 1)
>   (provide/contract [x (number? . -> . number?)]))
>
> (module n scheme
>   (require 'm)
>   (x #f))
>
> (require 'n)

(number? . -> . number?) shows off PLT's "infix notation" syntax.

(a . b . c) becomes (b a c)

leppie

unread,
Feb 17, 2009, 11:54:45 PM2/17/09
to
On Feb 17, 7:06 pm, kub <wareverboh...@gmail.com> wrote:

> Looks like we all are spinning around the same ideas :)
> Since contract library is needed anyway for r6rs wouldn't it
> be better to join our efforts ?
>

I believe Derrick Eddington also made a full-featured contract
library. In my case, I just need something simple to check incoming
arguments. Do you have a URL to your library perhaps?

> > The only part that is non-R6RS is string-split as I like to make my
> > parameters like: foo:bar where foo is the name, bar is the 'type' that
>
> I do not feel that joining argument identifier and argument type
> predicate is a good idea. It couldn't solve contracts problem
> since argument contracts can be (and in many cases are) much more
> complicated than dumb predicate check. Please correct me if i did
> understand your implementation incorrectly.

That is true, but my need for the library was purely convenience for
library writer point of view, asserting argument types gets a bit
tedious.

If the check is more complex than a predicate, or something that can
be defined as one, eg number-smaller-than-10-and-larger-than-5?, then
I would simply just check it 'normally' at the start of the procedure.
Like said, the motivation was convenience rather than a strict
contract definition (I dont really care for checking return values, as
I am returning it).

Cheers

leppie

Derick Eddington

unread,
Feb 18, 2009, 1:50:13 AM2/18/09
to
On Feb 17, 4:41 am, kub <wareverboh...@gmail.com> wrote:
> The only implementation-dependent part of assert is message in
> message-condition, right?

That depends on how you interpret "If <expression> returns #f, an
exception with condition types &assertion and &message is raised.".
Does that mean it can only contain those conditions?

$ cat assert.sps
(import (rnrs (6)))
(assert (not 'foo))
$ ikarus --r6rs-script assert.sps
Unhandled exception:
Condition components:
1. &assertion
2. &who: assert
3. &message: "assertion failed"
4. &irritants: ((not 'foo))
5. &source-position:
file-name: "assert.sps"
character: 21
$ larceny -r6rs -program assert.sps
Error: no handler for exception #<record &compound-condition>
Compound condition has these components:
#<record &assertion>
#<record &message>
message : "assertion failed"
#<record &irritants>
irritants : ((not 'foo))

Terminating program execution.
$ ypsilon --dump-condition assert.sps
error: assertion failed in expression (not 'foo)

#<condition
&assertion (&violation &serious)
&message: assertion failed in expression (not 'foo)
&irritants: ()
>

backtrace:
0 (assertion-violation #f "assertion failed in expression (not
'foo)")

$

> In this case I see no problem with portability, do you?

I think I do. In order for exceptions' information to be useful
programmatically and portably, it needs to be represented in a
portable (consistent) way. Even if assert's message strings were
portable, having to parse information out of them would be stupid,
especially since general purpose portable condition types are
available.

If assert is only used for debug mode then portable programmatic
usefulness probably isn't needed. But if assert is used for argument
checking then I think it is needed.

I test that my procedures' exceptions are portable. I test their main
condition (&assertion, &error, &warning, &i/o, etc.) and the fields'
values of their &who, &message, &irritants or whatever. Being able to
test code on multiple systems is one reason for argument check
exceptions to be useful portably.

Just like how exceptions are used in precise portable ways for
programs to decide how to handle exceptional situations other than bad
arguments, programs should be able to decide how to handle bad
argument exceptions and for this they need information. This could be
useful for a program that supervises other programs and wants to know
precisely who failed and for what reason, rather than just "some
argument check failed", so it can decide what to do based on that
information. I see this as following the spirit of making things
useful for all the future uses and complexity growth we can't
foresee. I don't think the language standard should attempt to figure
this out, but I think it should have portable consistent exceptions
for its things.

> > With compatibility libraries, implementations can
> > provide their things that tell file name, line number, etc.
>
> 100% agree. It is the most annoying thing about assert.

What do you mean?

--
: Derick
----------------------------------------------------------------

Derick Eddington

unread,
Feb 18, 2009, 2:39:36 AM2/18/09
to
On Feb 17, 8:54 pm, leppie <xacc....@gmail.com> wrote:
> I believe Derick Eddington also made a full-featured contract
> library.

I didn't. I just have an argument checking macro:

> (import (xitomatl define))
> (define/? (p a (b string?) c
(d (lambda (x) (and (integer? x) (exact? x))))
(e (if (null? a) vector? list?))
. #(args (lambda (x) (andmap pair? args))))
(list a b c d e args))
> (p 1 "two" 3 4 5 '(6 . 7))


Unhandled exception
Condition components:
1. &assertion

2. &who: p
3. &message: "argument check failed"
4. &irritants: (5)
5. &argument-name: e
6. &predicate: (if (null? a) vector? list?)
>

(I think I should rename &predicate to &predicate-expression.)

And some macros like:

> (define/who (foo) who)
> (foo)
foo
> (define/AV (bar) (AV "oops"))
> (bar)


Unhandled exception
Condition components:
1. &assertion

2. &who: bar
3. &message: "oops"
4. &irritants: ()
>

> (I dont really care for checking return values, as I am returning it).

Me neither.

--
: Derick
----------------------------------------------------------------

Michael Sperber

unread,
Feb 18, 2009, 3:28:40 AM2/18/09
to

Derick Eddington <derick.e...@gmail.com> writes:

> On Feb 16, 11:20 pm, Michael Sperber <sper...@deinprogramm.de> wrote:
>> Derick Eddington <derick.edding...@gmail.com> writes:
>> > When and why would a call to assertion-violation or assert be a tail
>> > call?  Please point us to somewhere we can see that this has been done
>> > often or give us an example that shows why it would be done often.
>>
>> This is a fairly common pattern:
>>
>> (define (proc arg)
>>   (if (ok? arg)
>>       (compute arg)
>>       (assertion-violation 'proc "arg not ok" arg")))
>
> Right, but assertion-violation never returns so I don't find this case
> justifying. I mentioned "assertion-violation or assert" because you
> mentioned only assertion-violation and I wasn't sure what you meant.

There's probably a misunderstanding at work: In common implementations
of tail recursion, if the assertion violation in the above example
happens, the frame for the call to `proc' will have disappeared: It is
therefore up to the message with `assertion-violation' to tell you where
the violation happened; the "stack trace" won't tell you.

I forgot you'd also asked about `assert' - sorry about that.

> What's an example, of a case that would occur often, of assert being
> in tail position where its return value would actually be used?

I don't know - it does seem hard to imagine such a scenario.

Derick Eddington

unread,
Feb 18, 2009, 5:25:50 AM2/18/09
to
On Feb 18, 12:28 am, Michael Sperber <sper...@deinprogramm.de> wrote:
> There's probably a misunderstanding at work: In common implementations
> of tail recursion, if the assertion violation in the above example
> happens, the frame for the call to `proc' will have disappeared: It is
> therefore up to the message with `assertion-violation' to tell you where
> the violation happened; the "stack trace" won't tell you.

I thought you were mentioning tail calls as a reason for assert
returning a value. Sorry for assuming too much about what you said.

So, the stack frame being reused if assertion-violation is tail-called
is why we need R6RS's assert. But error and other exception raisers
have the same tail call issue but they have no analogous alternative.
If I were to use assert for argument checking, it wouldn't be in tail
position because I'd do the check in the assert before the other
expressions. It seems to me this all is really an argument for not
using exception raisers in tail position so we can have better stack
traces.

I know assert is a minor issue so I'll drop it now. I've just been
getting more and more frustrated trying to understand R6RS.

--
: Derick
----------------------------------------------------------------

leppie

unread,
Feb 18, 2009, 7:31:17 AM2/18/09
to
On Feb 18, 12:25 pm, Derick Eddington <derick.edding...@gmail.com>
wrote:

>


> So, the stack frame being reused if assertion-violation is tail-called
> is why we need R6RS's assert.  But error and other exception raisers
> have the same tail call issue but they have no analogous alternative.
> If I were to use assert for argument checking, it wouldn't be in tail
> position because I'd do the check in the assert before the other
> expressions.  It seems to me this all is really an argument for not
> using exception raisers in tail position so we can have better stack
> traces.

By just using assert (with the default implementation message) will
not generally give you sufficient information where the error occured
(with the exclusion of psyntax providing a source location :) ).

By using assertion-violation, you generally supply a helpful message
and who.

It would have been nice if assert (and assertion-violation with a #f
who) could have had some implementation defined lookup, similar to
what syntax-violation does, but from the R6RS and the PLT tests, it
seems this is against the law!

Cheers

leppie

kub

unread,
Feb 18, 2009, 8:44:33 AM2/18/09
to
On Feb 18, 8:50 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

> On Feb 17, 4:41 am, kub <wareverboh...@gmail.com> wrote:
>
> That depends on how you interpret "If <expression> returns #f, an
> exception with condition types &assertion and &message is raised.".
> Does that mean it can only contain those conditions?

I think no and IMO assert is not enough standardized.

<snip>


> > > With compatibility libraries, implementations can
> > > provide their things that tell file name, line number, etc.
>
> > 100% agree. It is the most annoying thing about assert.
>
> What do you mean?

That lack of standard on source position information in assert and
other places like syntax-violation causes lot of problems in portable
r6rs programming and especially for portable development tools.

--
Bogdan

kub

unread,
Feb 18, 2009, 9:14:00 AM2/18/09
to
On Feb 18, 6:54 am, leppie <xacc....@gmail.com> wrote:
> On Feb 17, 7:06 pm, kub <wareverboh...@gmail.com> wrote:
>
> I believe Derrick Eddington also made a full-featured contract
> library. In my case, I just need something simple to check incoming
> arguments. Do you have a URL to your library perhaps?

Not yet. Next month I'll be busy but after that i'll write some minor
docs and will put everything on launchpad.

Meanwhile short description:
Core is constraints library which is basically a tool for building
predicates to check values and emit human readable information in
case of failure. On top of this library there are two others:
contracts
and unit-testing (integration into Vim/Gvim provided).
GVim integration includes possibility to run particular test, test-
fixture or test-suite using your mouse only (like in TestDriven.Net)
and see list of errors in vim's quickfix window.
At the end you can find constraints tests snippets.

> Like said, the motivation was convenience rather than a strict
> contract definition (I dont really care for checking return values, as
> I am returning it).

I understand this, *but* by specifying contract for returned value you
also document your code (idea from PLT). Having nice macros for
contracts you can generate reasonable documentation having simple doc
tool. You will rarely need this functionality in project which
contains single
developer ... but in case of team specifying return value can avoid a
lot of problems.
Now extend contracts idea on exceptions too. Are you sure that you can
easily remember and control all exceptions raised by your procedure ?

--
Bogdan

Constraints tests snippet:

<code>
(expect-diagnosis
(verify 'foo (or/c number? string?))
'(got (symbol foo)
(expected: number?)
(expected: string?)))

(expect-diagnosis
(verify '(a . b) (pair/c symbol? string?))
'(got (pair (a . b))
(for cdr
(got (symbol b)
(expected: string?)))))

(expect-diagnosis
(verify '(a "b" "444") (list/c symbol? string? number?))
'(got (list (a "b" "444"))
(for (item-at-index 2)
(got (string "444")
(expected: number?)))))

(expect-diagnosis
(verify "126"
(for/c string-length
(and/c (>=/c 5) (<=/c 10))))
'(got (string "126")
(for string-length
(got (number 3)
(expected: (>= 5))))))

(expect-success
(verify (partition even? '(3 1 4 1 5 9 2 6))
(values/c list? list?)))
</code>

Derick Eddington

unread,
Feb 18, 2009, 7:43:46 PM2/18/09
to
On Feb 18, 5:44 am, kub <wareverboh...@gmail.com> wrote:
> On Feb 18, 8:50 am, Derick Eddington <derick.edding...@gmail.com>
> > > > With compatibility libraries, implementations can
> > > > provide their things that tell file name, line number, etc.
>
> > > 100% agree. It is the most annoying thing about assert.
>
> > What do you mean?
>
> That lack of standard on source position information in assert

Making an independent portable assert is doable with compatibility
libraries and if systems provide equivalent functionality (or at least
functionality which can be made to be equivalent):

(library (acme assert)
(export
assert
debug-mode
expression-condition?
condition-expression
source-location-condition?
condition-source-location-file-name
condition-source-location-character-position
condition-source-location-procedure-name)
(import
(except (rnrs) assert)
(acme assert compat)) ;; Assumes implicit phasing :-)

(define-condition-type &expression &condition
make-expression-condition expression-condition?
(expression condition-expression))

(define-condition-type &source-location &condition
make-source-location-condition source-location-condition?
(file-name condition-source-location-file-name)
(character-position condition-source-location-character-position)
(procedure-name condition-source-location-procedure-name))

(define (assert-failed expr file-name char-pos proc-name)
(raise (condition
(make-assertion-violation)
(make-message-condition "debugging assertion failed")
(make-expression-condition expr)
(make-source-location-condition file-name char-pos proc-
name))))

(define-syntax assert
(lambda (stx)
(if (debug-mode)
(syntax-case stx ()
((_ expr)
(let ((file-name (source-file-name stx))
(char-pos (source-character-position stx))
(proc-name (source-containing-procedure-name stx)))
#`(if expr
(values)
(assert-failed 'expr #,file-name #,char-pos '#,proc-
name)))))
;; Compilers should know when this is a superfluous
;; expression and eliminate it.
#'(values))))
)

(library (acme assert compat)
(export
debug-mode
source-file-name
source-character-position
source-containing-procedure-name)
(import
(only (ultra-scheme debugging)
debug-mode)
(only (ultra-scheme syntax-utilities)
source-file-name
source-character-position
source-containing-procedure-name))

;; Or maybe build on Ultra Scheme's functionality to make what we
need...
)

(library (acme assert compat)
(export
debug-mode
source-file-name
source-character-position
source-containing-procedure-name)
(import
(rnrs)
(srfi :39 parameters))

(define debug-mode (make-parameter #T))

(define (source-file-name stx)
"foo/bar.sls")

(define (source-character-position stx)
12345)

(define (source-containing-procedure-name stx)
#'do-something)
)

Under Ikarus:

> (import (acme assert))
> (assert (not 'true))


Unhandled exception
Condition components:
1. &assertion

2. &message: "debugging assertion failed"
3. &expression: (not 'true)
4. &source-location:
file-name: "foo/bar.sls"
character-position: 12345
procedure-name: do-something
> (parameterize ((debug-mode #F))
(eval '(begin (assert (not 'true))
'done)
(environment '(except (rnrs base) assert)
'(acme assert))))
done
> (debug-mode #F)
> (assert (not 'true))
>

--
: Derick
----------------------------------------------------------------

Michael Sperber

unread,
Feb 19, 2009, 8:53:36 AM2/19/09
to

Derick Eddington <derick.e...@gmail.com> writes:

> So, the stack frame being reused if assertion-violation is tail-called
> is why we need R6RS's assert. But error and other exception raisers
> have the same tail call issue but they have no analogous alternative.
> If I were to use assert for argument checking, it wouldn't be in tail
> position because I'd do the check in the assert before the other
> expressions.

You're right: I doubt there's a strong rationale for `assert' returning
the value of its operand. As you can imagine, `assertion-violation',
`error' and `syntax-violation' were there first (reflecting the most
important entry points into the condition hierarchy), and `assert' was
added, I believe, to duplicate similar-looking functionality in, say,
Java or C.

kub

unread,
Feb 19, 2009, 9:17:55 AM2/19/09
to
Exactly! Since original assert is nearly unusable.
It would be nice if you add it to your libraries set
or even do SRFI (want too much ?).

Only my 5c:
1. IMHO it should be position
instead of character-position since byte counting is more
natural than character counting which assumes particular
encoding.

2. Alternatively to counting position or line/column it is possible
to use syntax object as source position information.
AFAIK all existing implementations allow to obtain source position
information from syntax-object. If standard forced this fact then
there will be no need in separate expression condition and source
position condition. Also it can help in
standardization of syntax-violations.

3. R6RS defines &assertion for argument check only.
Your assert is mentioned debug-assert which is *completely*
different from argument checking. It means that you should
use your own condition or *fix* meaning of standard &assertion.

--
Bogdan

On Feb 19, 2:43 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

Derick Eddington

unread,
Feb 19, 2009, 10:34:05 PM2/19/09
to
On Feb 19, 6:17 am, kub <wareverboh...@gmail.com> wrote:
> It would be nice if you add it to your libraries set
> or even do SRFI (want too much ?).

Maybe another time. Feel free to do whatever you want with that draft
(acme assert).

> Only my 5c:
> 1. IMHO it should be position
> instead of character-position since byte counting is more
> natural than character counting which assumes particular
> encoding.

I think the opposite. Textual source-code is in terms of characters.
I don't care what byte it was at -- that assumes a particular
encoding.

> 2. Alternatively to counting position or line/column it is possible
> to use syntax object as source position information.
> AFAIK all existing implementations allow to obtain source position
> information from syntax-object. If standard forced this fact then
> there will be no need in separate expression condition and source
> position condition. Also it can help in
> standardization of syntax-violations.

Well, I'm becoming more and more convinced that if it can be done
independently via compatibility libraries there's no reason to weigh
down the language standard (and the people who spend time on it) and
force implementors with legislated assumptions that might not be what
everyone wants. After all, Scheme source-code is actually a data
structure we only view as a textual representation, and so it's
possible (and one of the more unique useful awesome things about
Scheme) source-code which was not "read in" very well may be evaluated
and it would have no textual source location. With compatibility
libraries, if an implementation doesn't provide whatever necessary
support, it won't have a compatibility library and so attempting to
use it will fail to find the library, which will let you know what is
needed so you can lobby that implementation to add support.

> 3. R6RS defines &assertion for argument check only.
> Your assert is mentioned debug-assert which is *completely*
> different from argument checking. It means that you should
> use your own condition or *fix* meaning of standard &assertion.

I say the meaning of &assertion should match its very general name.
Since conditions are compound and the types extensible, it's really
the entire "shape and color" that determines the full meaning, and I
think this is a main quality that makes them so flexibly useful. A
sub-type of &assertion could be made for failed argument checks, or a
separate type; I don't know what would be better.

--
: Derick
----------------------------------------------------------------

leppie

unread,
Feb 20, 2009, 2:24:10 AM2/20/09
to
On Feb 20, 5:34 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

> On Feb 19, 6:17 am, kub <wareverboh...@gmail.com> wrote:
> > Only my 5c:
> > 1. IMHO it should be position
> >  instead of character-position since byte counting is more
> >  natural than character counting which assumes particular
> >  encoding.
>
> I think the opposite.  Textual source-code is in terms of characters.
> I don't care what byte it was at -- that assumes a particular
> encoding.
>

I still feel the line and column combo is the best indicator of
errors, preferably with an 'end' column and 'end' line too.

This way a text editor needs not to know anything about the language.

Cheers

leppie

kub

unread,
Feb 20, 2009, 3:57:44 AM2/20/09
to
On Feb 20, 9:24 am, leppie <xacc....@gmail.com> wrote:
> wrote:
<snip>

> I still feel the line and column combo is the best indicator of
> errors, preferably with an 'end' column and 'end' line too.
>
> This way a text editor needs not to know anything about the language.

+1. Besides line numbering is less sensitive to encoding.

--
Bogdan

Michael Sperber

unread,
Feb 23, 2009, 2:17:46 AM2/23/09
to

kub <wareve...@gmail.com> writes:

> Exactly! Since original assert is nearly unusable.

Unusable? I use it all the time, and it works pretty well for me.

leppie

unread,
Feb 23, 2009, 3:22:51 AM2/23/09
to
On Feb 23, 9:17 am, Michael Sperber <sper...@deinprogramm.de> wrote:

It would be more usable if you could include an optional message, who
and irritants. Currently the R6RS does not even allow the who part to
be 'auto-detected' when given an #f argument.

It works well for simple cases though.

Cheers

leppie

kub

unread,
Feb 25, 2009, 3:18:14 PM2/25/09
to
1. You can not use it as debug-assert (turned-off in release) because
- r6rs says it is for procedure argument checking only
- because it can not be turned off (r6rs allows to return value).
;; Debug assert is normal semantics of assert in c/c++.

2. Procedure argument checking via assert semantics is nearly unusable
since it
- doesn't provide information about irritants (impossible to eval
them)
- provides no standardized information to highlight source position
of failure i.e. it is impossible to write portable development
tool (IDE, editor ...) capturing this information.
- provides no possibility to supply custom message which explains
details of argument rejection.

Also you can not use assertion-violation directly to have better
argument checking just because it does not provide source locations
information which is *must* for development.

Note that procedure argument checking coding style should be const
from the beginning of your project. Normally developer should not
spend week to fix all argument checking just because r7rs has some
"better idea" ...

That is why i prefer to write my own debug-assert, contract checking
asserts and not to use assert/assert-violation directly.

--
Bogdan

On Feb 23, 9:17 am, Michael Sperber <sper...@deinprogramm.de> wrote:

0 new messages