Here's an example using compile time reflection. With __traits(allMembers), we can loop through the names of all members in an aggregate (module, struct, class, etc.) and with __traits(getMember), we can fetch a member by name and do stuff like call it.
The tricky part is getMember requires a compile time string, so we can't just pass it the command line argument directly. Instead, we build a switch to dispatch from the argument - almost just like you would by hand, but instead of writing all the names yourself, you let the loop handle it.
There's only two functions here, but it will scale to any number of them without needing to modify the main function.
See more comments inline:
import std.stdio;
// I'm grouping all the commands in a struct
// so it is easier to loop over them without
// other stuff getting in the way
struct Commands {
// making them all static so we don't need to instantiate it
// to call commands. This is often not the best way but it makes
// for an easy demo and does work well a lot of the time.
static:
// Also assuming they all return void and have no arguments.
// It is possible to handle other things, but it gets a lot
// more involved. (I think my book example goes partially into
// it, or something like my web.d goes all the way and generates
// web/http and javascript/json apis from a full signature but that
// code is pretty unreadable...)
void func001() {
writef("func001 called\n");
}
void func002() {
writef("func002 called\n");
}
}
void main(string[] args) {
if(args.length > 1)
// we switch on the runtime value..
// the label will be used below
outer: switch(args[1]) {
// then loop through the compile time options to build
// the cases. foreach with a compile time argument works
// a bit differently than runtime - it is possible to build
// switch cases with it.
//
// See also: http://dlang.org/traits.html#allMembers
// and the sample chapter of my book
foreach(memberName; __traits(allMembers, Commands)) {
case memberName:
// get the member by name with reflection,
// and call it with the parenthesis at the end
__traits(getMember, Commands, memberName)();
// breaking from the labeled switch so we don't fallthrough
// and also won't break the inner loop, which we don't want.
break outer;
}
default: // default is required on most D switches
writef("No such function, %s!\n", args[1]);
break;
}
else { // insufficient args given
writeln("Argument required. Options are:");
// we can also loop to list names at runtime
foreach(memberName; __traits(allMembers, Commands)) {
writeln(memberName);
}
}
}
char[][]should bestring[]in modern D btw.