feedback wanted on better assert

5 views
Skip to first unread message

Stuart Halloway

unread,
Jul 29, 2010, 12:47:30 PM7/29/10
to cloju...@googlegroups.com
This would make my life easier. Probably could be nicer implementation, might need other features.

https://www.assembla.com/spaces/clojure/tickets/415-smarter-assert-(prints-locals)

Thoughts?

Peter Schuller

unread,
Jul 29, 2010, 1:27:46 PM7/29/10
to cloju...@googlegroups.com
> This would make my life easier. Probably could be nicer implementation, might need other features.
>
> https://www.assembla.com/spaces/clojure/tickets/415-smarter-assert-(prints-locals)
>
> Thoughts?

Awesome idea. I don't know how many times I have had to tweak code and
re-run to figure out *why* an assertion failed (regardless of
programming language).

One problem I can think of is that locals may contain things that you
definitely do not want to print (infinite sequences, very large data
structures, even sequences whose consumption implies some kind of
side-effect).

Unfortunately I don't have a suggestion as to how to get around that
problem that does not involve somehow manually selecting which locals
are to be printed, significantly reducing the out-of-the-box
usefulness of the macro.

--
/ Peter Schuller

Peter Schuller

unread,
Jul 29, 2010, 1:48:28 PM7/29/10
to cloju...@googlegroups.com
> Unfortunately I don't have a suggestion as to how to get around that
> problem that does not involve somehow manually selecting which locals
> are to be printed, significantly reducing the out-of-the-box
> usefulness of the macro.

Hmm, maybe something pragmatic like filtering types and applying some
custom behavior for each. For example a map could be printed if it
contains less than N associations (or else print up to N
associations), and values in said map never printed except if they are
primitives or non-clojure data structures (that was not terribly
thought-through).

Might it be appropriate to define a protocol for printing objects
"safely" for debugging purposes, and then have assert use that? I'm
thinking something along the lines of combining Common Lisp-style
print-object with Smalltalk style inspection. Maybe:

(inspect x) ; inspection equivalent of print
(str-inspect x) ; inspection equivalent of str

Both dispatching on x via a protocol.

--
/ Peter Schuller

Jason Wolfe

unread,
Jul 29, 2010, 1:48:44 PM7/29/10
to Clojure Dev
That could be very useful, although I'd be somewhat concerned about
being swamped with text when I have a local bound to a 10 MB data
structure.

I have a somewhat similar macro I use, with a different set of
features:

user> (let [sky "blue"] (assert-is (= (inc 1) (dec 4)) "The sky is %s"
sky))

The sky is blue: Assertion (= (inc 1) (dec 4)) failed, got (= 2 3)
[Thrown class java.lang.Exception]


The features are:
- Assumes the form consists of a predicate applied to some sub-
expressions. In addition to printing the form, also prints the form
with the sub-expressions evaluated, which I find really useful in
cases where they are non-trivial functions of the locals. Of course,
this only works when the form is a functional form (not an atom, or a
macro application), and is rather useless when the expression is
(assert (not (= ...))), for example. Perhaps there's a nice way to
generalize this, but I'm not sure. I suppose that you can manually get
this effect with locals-printing by just letting the sub-exprs before
the assert, but you have to do that by hand.

- Allows an optional custom format string and accompanying args to
come after the form to be tested. This allows you to show arbitrary
additional information in the assertion error, e.g. for (apply = huge-
data-structures), you might want to show the diff. I'm not sure that
the format string approach is the most elegant, but that could easily
be changed.

If either of these are of interest, I'd be happy to help work on
adding them to the proposed macro.

-Jason




Allen Rohner

unread,
Jul 29, 2010, 2:59:31 PM7/29/10
to Clojure Dev
I've been meaning to post two enhancements I'd like to see in assert:

1) Make it return the expression, if it passes. This allows you to do
things like:

(let [foo (assert (bar x))])

The workaround is a little ugly:

(let [foo (bar x)
_ (assert foo)])

2) Take an optional message to include in the assertion failure

(assert (positive? x) "x must be positive")

Allen

Alex Miller

unread,
Jul 29, 2010, 3:12:20 PM7/29/10
to cloju...@googlegroups.com
Would you be better served by just using preconditions for these cases?


From: Allen Rohner <aro...@gmail.com>
To: Clojure Dev <cloju...@googlegroups.com>
Sent: Thu, July 29, 2010 1:59:31 PM
Subject: Re: feedback wanted on better assert
--
You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
To post to this group, send email to cloju...@googlegroups.com.
To unsubscribe from this group, send email to clojure-dev+unsub...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/clojure-dev?hl=en.

Reply all
Reply to author
Forward
0 new messages