On 2011-01-06 01:36:32 -0500, Jonathan M Davis <jmdavisp...@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.for...@michelf.com
http://michelf.com/

Reply via email to