change mixins

Nick Sabalausky a at a.a
Mon Feb 15 20:21:38 PST 2010


"grauzone" <none at example.net> wrote in message 
news:hlbg22$6fb$1 at digitalmars.com...
> Nick Sabalausky wrote:
>> "BCS" <none at anon.com> wrote in message 
>> news:a6268ff103d38cc7ba48d6fabda at news.digitalmars.com...
>>> Hello Nick,
>>>
>>>> I *definitely* want that for string mixins of both the
>>>> template-generated and ctfe-generated varieties.
>>>>
>>> Why? I don't see any reason aside from documentation to do it.
>>>
>>
>> Well, for one thing, not having it forces any code using my custom-assert 
>> library to look like this crap...
>>
>> mixin(deferAssert!(`foo == 3 || foo > 5`, "foo is bad"));
>>
>> ...which understandably no one wants to touch and I *absolutely* don't 
>> blame them one bit. Compare that to this...
>>
>> deferAssert!(`foo == 3 || foo > 5`, "foo is bad");
>>
>> ...ahhh, now I can actually see what the hell's going on!
>>
>
> Now come on, the second one also looks ugly and confusing as hell. Sure, 
> mixins are powerful (and sometimes I couldn't avoid using them myself), 
> but really, I never understood what people like about writing code into 
> STRING LITERALS.

I certainly agree with that, but until we get AST macros or at least some 
movement in that direction, this sort of thing is often the best we can do.


> At least with the mixin you see in which context the code will be compiled 
> (though only roughly), unlike the second line of code, which just 
> obfuscates the code further.
>

I can understand that. Not sure I agree, but I can certainly see what you 
mean.


> And the only reason why you need this for your asserts is that you want to 
> get the location of the failing assert. That's mostly because of D's 
> lacking backtrace abilities of D (defAssert just had to resolve the 
> location of the previous stackframe).
>
> On the other hand, I heard D2 has an ugly trick to get the caller's 
> location:
> dd ddd
> void defAssert(bool condition, cha^Wstring message, string file = 
> __FILE__, int line = __LINE__);
>
> defAssert(condition, message);

Maybe it's not clear from that code, but there's more to it than that:

One of the main ideas behind that lib (aside from unittests that don't exit 
on the first failure), is to get detailed unittest diagnostics that are 
comparable to what one gets from something like JUnit/NUnit, but with 
something much closer to actual syntax than obfuscated crap like:

Assert.AreEqual(x, y); // And it just gets worse from here...

// Actual examples from NUnit's documentation
Assert.That( myString, Is.EqualTo("Hello") );
Assert.That(5, Is.InstanceOfType(typeof(string)));
Assert.That( 5, Is.Not.SubsetOf( iarray ) );

Unittesting frameworks have garbage fake-syntax like that so that (without 
making the user violate DRY and state every assert in both real code for the 
first param and then again in plain english in the second param), it can 
respond to a failure by providing detailed information like:

foo.cs(17): Wrong value in variable "bar". Was 3, but expected greater than 
5.

Instead of:

foo.cs(17): Assert failure: "Wrong value"

But with D's string mixins and metaprogramming, we can get diagnostics that 
are nearly as good, but with syntax that differs from normal expressions in 
little more than just sticking a few quotes around things. Not perfect, 
granted, but one hell of an improvement.





More information about the Digitalmars-d mailing list