std.unittests for (final?) review

Michel Fortin michel.fortin at michelf.com
Thu Jan 6 05:30:56 PST 2011


On 2011-01-06 01:36:32 -0500, Jonathan M Davis <jmdavisProg at gmx.com> said:

> Okay. I thought this through a bit more, and I think that if the evaluation was
> stopped when all that was left in the expression was boolean operators 
> and their
> operands, then that pretty much has to be what the programmer was trying to
> print. That being the case, you could theoretically get assert to do it, but I
> would expect that that would make assert awfully complicated. Done properly, it
> would be fantastic, but since it can be done in a library with something like
> assertPred!() much more easily, I wouldn't expect such an enhancement to assert
> to be implemented any time soon.

Some people though const(Object)ref was impossible too.

I agree that assertPred!() is useful in the meanwhile.


> A few of the things that I'm thinking of doing with assertPred!() have to be
> special cased though in a way which wouldn't work with assert. For 
> instance, I'm
> thinking of doing something like assertPred!("opCmp", 0)(foo(), bar()), which
> would do what assertOpCmp!() does now. As such, opCmp() isn't a predicate, if
> you rewrote it to assert(foo().opCmp(bar()) == 0), even stopping 
> evaluation when
> all you have left is boolean operators and their operands wouldn't work, since
> then you'd get something like 1 == 0 rather than (assuming that foo() and bar()
> return something like BigInts which have the values "4" and "2" respectively)
> something like "opCmp() == 0 failed: 4 > 2".

For these cases you might prefer a custom assertion function, such as 
assertOpCmp!(). I think it's important that assert be useful for the 
common case, it doesn't mean that more specialized solutions cannot be 
created for more specialized cases, such as this one.


> Sure, you could make it so that assert could do that sort of thing too, 
> but then
> you're adding special cases and complicating assert even further, and it's also
> much harder to add such cases, because then you're actually changing the
> _language_ rather than the standard library, and every compiler would have to
> follow suit.

It's a quality of implementation issue. What error message an assert 
gives is no more part of the language than what error message the 
compiler outputs when it encounters some incorrect code. The compiler 
could simply print "error" each time it encounters an error and it'd be 
compliant (even though that would be extremely annoying).

Beside, all the current working compilers share the same front end, so 
they'll all get this for free.

So I think it's worth it.


> So, yes assert could theoretically be improved to do a lot more and do a lot
> better, but it won't ever do as much as I could do with assertPred!(), and even
> if assert _is_ improved as you suggest (which would certainly be cool), then
> there's still some value in assertPred!().

There's an other issue that's bothering me with these assertion 
functions... with 'assert', assertions behaves differently depending on 
where you write them. In regular code, on failure it calls _d_assert*, 
in a unit test on failure it calls _d_unittest*, and in contracts for 
virtual function... well that case I don't understand it fully but it 
does something very special to implement contract inheritance.

What does assertPred do? It does "throw new AssertError(...)", 
irrespective of the context. I'm pretty sure that'll break contract 
inheritance if used inside a contract. To be truly a replacement for 
assert, assertPred would need to know in which context it is called and 
generate the appropriate code, although I somewhat doubt it is even 
possible to generate the right code for contracts without the compiler 
doing it.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/



More information about the Digitalmars-d mailing list