Compile-time optimization
H. S. Teoh
hsteoh at quickfur.ath.cx
Tue Jul 23 12:42:18 PDT 2013
On Tue, Jul 23, 2013 at 11:09:24AM -0700, H. S. Teoh wrote:
[...]
> Using tupleReduce, you can optimize calls to join by writing:
>
> join(tupleReduce!("a", "b", x, "c", "d"));
>
> and it will be compiled as though you've written:
>
> join("ab", x, "cd");
[...]
I've generalized tupleReduce to handle reduction of tuples by any
CTFE-able binary function:
import std.stdio;
template tuple(args...) {
alias tuple = args;
}
/**
* Given a binary function and a tuple, returns a tuple in which all adjacent
* compile-time readable items are recursively substituted with the return
* value of the binary function applied to them.
*/
template tupleReduce(alias func, args...)
{
static if (args.length > 1)
{
static if (__traits(compiles, { enum x = args[0]; }))
{
static if (__traits(compiles, { enum x = args[1]; }) &&
is(typeof(func(args[0], args[1]))))
{
enum result = func(args[0], args[1]);
alias tupleReduce = tupleReduce!(func, result,
args[2..$]);
}
else
{
alias tupleReduce = tuple!(args[0], args[1],
tupleReduce!(func, args[2..$]));
}
}
else
{
alias tupleReduce = tuple!(args[0],
tupleReduce!(func, args[1..$]));
}
}
else
{
alias tupleReduce = args;
}
}
/**
* Given a tuple of strings, returns a tuple in which all adjacent compile-time
* readable strings are concatenated.
*/
template tupleStringReduce(args...)
{
alias tupleStringReduce = tupleReduce!(
(string x, string y) => x~y, args
);
}
void main() {
string x = "runtime1";
string y = "runtime2";
auto arr = [ tupleStringReduce!("a", "b", x, "c", "d", y, "e", "f", "g", x) ];
writeln(arr);
int i1=100, i2=200;
auto brr = [ tupleReduce!((int x, int y) => x+y, 1, 2, i1, 3, 4, i2, 5, 6, 7) ];
writeln(brr);
}
The output is:
["ab", "runtime1", "cd", "runtime2", "efg", "runtime1"]
[3, 100, 7, 200, 18]
For the string case, to make user code more convenient, I've written an
alias template tupleStringReduce() that basically supplies the binary
function for concatenating adjacent strings.
The second case shows how this can be explicitly specified via a
function literal. The example here reduces adjacent compile-time
readable ints via addition; you could substitute that with any binary
function you want, say (x,y)=>x*y, or (x,y)=>x*2-y, or whatever. The
only limit is that the function must be CTFE-able.
With the help of the new tupleReduce, you can do all sorts of
compile-time optimizations.
D gives you power -- awesome power -- but you do have to learn how to
tame the beast first. ;-)
T
--
Beware of bugs in the above code; I have only proved it correct, not tried it. -- Donald Knuth
More information about the Digitalmars-d
mailing list