|
Archives
D Programming
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.ide
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
D.gnu
D
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
electronics
|
digitalmars.D - A thought for template alias parameters?
I'm working on a set of handy unit testing accessories for my projects. What
I'd love to achieve is something like this:
expectEqual( myFoo, 3 );
Which, on failure, would result in something along the lines of this diagnostic:
somefile.d:37: Test failure!
Expected: myFoo == 3
Actual: 100, 3
Using a bit of template magic with alias parameters, I've come close:
void expectEquals(alias A, alias B)
( string file = __FILE__, int line = __LINE__ )
{
if(A != B) {
writefln( "Error: %s, line %d", file, line );
writefln( " expected: %s == % s", A.stringof, B.stringof );
writefln( " actual: %s, %s", A, B );
}
}
void main() {
int myFoo = 100;
expectEquals! ( myFoo, 3 );
}
This will produce the output
Error: test.d, line 33
expected: myFoo == 3
actual: 100, 3
Unfortunately, this isn't quite there yet. Alias parameters can only match
single symbols, so something like this won't compile:
int myFoo = 100;
int myArray[5];
expectEquals! ( myFoo, myArray[0] );
So my question is, would it be a good idea to add the ability in future
versions for template parameters to alias entire expressions? It would be
perfect for making templated assertions like this and probably has many other
metaprogramming applications. As a recent convert from C++, I still miss the
ability of macro systems (like GoogleTest) to print highly reflective unit test
assertion messages.
Would there be any drawbacks or difficulties in doing this that I'm completely
missing? :-P
On 2/3/2010 9:34 PM, Trip Volpe wrote:
I'm working on a set of handy unit testing accessories for my projects. What
I'd love to achieve is something like this:
expectEqual( myFoo, 3 );
Which, on failure, would result in something along the lines of this
diagnostic:
somefile.d:37: Test failure!
Expected: myFoo == 3
Actual: 100, 3
Using a bit of template magic with alias parameters, I've come close:
void expectEquals(alias A, alias B)
( string file = __FILE__, int line = __LINE__ )
{
if(A != B) {
writefln( "Error: %s, line %d", file, line );
writefln( " expected: %s == % s", A.stringof, B.stringof );
writefln( " actual: %s, %s", A, B );
}
}
void main() {
int myFoo = 100;
expectEquals! ( myFoo, 3 );
}
This will produce the output
Error: test.d, line 33
expected: myFoo == 3
actual: 100, 3
Unfortunately, this isn't quite there yet. Alias parameters can only match
single symbols, so something like this won't compile:
int myFoo = 100;
int myArray[5];
expectEquals! ( myFoo, myArray[0] );
So my question is, would it be a good idea to add the ability in future
versions for template parameters to alias entire expressions? It would be
perfect for making templated assertions like this and probably has many other
metaprogramming applications. As a recent convert from C++, I still miss the
ability of macro systems (like GoogleTest) to print highly reflective unit test
assertion messages.
Would there be any drawbacks or difficulties in doing this that I'm completely
missing? :-P
You could potentially use a mixin to do this. The resulting code would
look something like this.
void main()
{
int myFoo = 100;
mixin(expectEquals! ( "myFoo == 3" ));
}
Joel Anderson Wrote:
You could potentially use a mixin to do this. The resulting code would
look something like this.
void main()
{
int myFoo = 100;
mixin(expectEquals! ( "myFoo == 3" ));
}
Yeah, mixins could work, but they're ugly. ;-)
Forcing the user (in this case the unit test writer) to apply extra boilerplate
on their own every time they want to make an assertion is really not much of a
solution. There's no semantic reason an assertion should involve a mixin, so
allowing that detail to bleed into client code is shaky design.
I know I'd get tired of wrapping everything in mixin(...) all the time, and in
the end it would probably result in me writing fewer unit tests. :-P
On 2/3/2010 10:27 PM, Trip Volpe wrote:
Joel Anderson Wrote:
You could potentially use a mixin to do this. The resulting code would
look something like this.
void main()
{
int myFoo = 100;
mixin(expectEquals! ( "myFoo == 3" ));
}
Yeah, mixins could work, but they're ugly. ;-)
Forcing the user (in this case the unit test writer) to apply extra
boilerplate on their own every time they want to make an assertion is really
not much of a solution. There's no semantic reason an assertion should involve
a mixin, so allowing that detail to bleed into client code is shaky design.
I know I'd get tired of wrapping everything in mixin(...) all the time, and in
the end it would probably result in me writing fewer unit tests. :-P
That's one of the reasons I've wished D had a nicer syntax for the
string mixin format. This one kinda scares people away :p
Joel Anderson Wrote:
That's one of the reasons I've wished D had a nicer syntax for the
string mixin format. This one kinda scares people away :p
What kind of syntax do you have in mind?
Making mixins less obtrusive might ease aggravation when they're being used as
boilerplate, but making it harder to see when they're being used might have
downsides as well. :-P
For a case like this, though, I still think the best solution would be to allow
for template parameters that can alias whole expressions. Together with the
other compile-time reflection abilities of D, I think it would make quite a
powerful tool.
On 2/4/2010 4:41 PM, Trip Volpe wrote:
Joel Anderson Wrote:
That's one of the reasons I've wished D had a nicer syntax for the
string mixin format. This one kinda scares people away :p
What kind of syntax do you have in mind?
Making mixins less obtrusive might ease aggravation when they're being used as
boilerplate, but making it harder to see when they're being used might have
downsides as well. :-P
Not sure. I'm sure there's a syntax that could meet both goals.
Something like.
void expectsEquals(string data)()
{
mixin(data);
}
...
expectsEquals!("myFoo == 3")();
or
expectsEquals!("myFoo == 3");
For a case like this, though, I still think the best solution would be to
allow for template parameters that can alias whole expressions. Together with
the other compile-time reflection abilities of D, I think it would make quite a
powerful tool.
On 2/5/2010 8:55 PM, Joel Anderson wrote:
On 2/4/2010 4:41 PM, Trip Volpe wrote:
Joel Anderson Wrote:
That's one of the reasons I've wished D had a nicer syntax for the
string mixin format. This one kinda scares people away :p
What kind of syntax do you have in mind?
Making mixins less obtrusive might ease aggravation when they're being
used as boilerplate, but making it harder to see when they're being
used might have downsides as well. :-P
Not sure. I'm sure there's a syntax that could meet both goals.
Something like.
void expectsEquals(string data)()
{
mixin(data);
}
I mean:
void expectsEquals(string data)()
{
mixin(dostuff(data));
}
...
expectsEquals!("myFoo == 3")();
or
expectsEquals!("myFoo == 3");
For a case like this, though, I still think the best solution would be
to allow for template parameters that can alias whole expressions.
Together with the other compile-time reflection abilities of D, I
think it would make quite a powerful tool.
On 02/06/2010 05:55 AM, Joel Anderson wrote:
On 2/4/2010 4:41 PM, Trip Volpe wrote:
Joel Anderson Wrote:
That's one of the reasons I've wished D had a nicer syntax for the
string mixin format. This one kinda scares people away :p
What kind of syntax do you have in mind?
Making mixins less obtrusive might ease aggravation when they're being
used as boilerplate, but making it harder to see when they're being
used might have downsides as well. :-P
Not sure. I'm sure there's a syntax that could meet both goals.
Something like.
void expectsEquals(string data)()
{
mixin(data);
}
...
expectsEquals!("myFoo == 3")();
or
expectsEquals!("myFoo == 3");
This syntax should be possible, which also gives syntax highlighting:
expectEquals!q{ myFoo == 3 };
But there is the problem that expectEquals is defined in a module which
doesn't have access to myFoo. I don't know how to solve that.
|
|