I'm currently in the requirements phase and doing some requirements gathering. To make sense of all this data I'm writing a tool in D to analyse it.
Unfortunately I had code such as:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
YesNoSometimes assmtfdbkParse(string text) { | |
string[] stes = text.split(","); | |
foreach(ste; stes) { | |
switch(ste) { | |
case "Yes definately": | |
return YesNoSometimes.Yes; | |
case "Depends on the student": | |
return YesNoSometimes.Sometimes; | |
default: | |
return YesNoSometimes.No; | |
} | |
} | |
return YesNoSometimes.No; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mixin template QParse(string name, string defaultv, RET, ARGS...) if ((EnumMembers!RET).length-1 == ARGS.length) { | |
mixin("""RET " ~ name ~ "(string text) { | |
string[] stes = text.split(\",\"); | |
foreach(ste; stes) { | |
switch(ste) { | |
" ~ QParseGrabCases!(RET, ARGS) ~ " | |
default: | |
return RET." ~ defaultv ~ "; | |
} | |
} | |
return RET." ~ defaultv ~ "; | |
}"""); | |
} | |
mixin template QParseOther(string name, RET, ARGS...) if ((EnumMembers!RET).length-1 == ARGS.length) { | |
mixin("""RET " ~ name ~ "(string text, ref string other) { | |
string[] stes = text.split(\",\"); | |
foreach(ste; stes) { | |
switch(ste) { | |
" ~ QParseGrabCases!(RET, ARGS) ~ " | |
case \"Other\": | |
continue; | |
default: | |
other = ste; | |
return RET.Other; | |
} | |
} | |
return RET.Other; | |
}"""); | |
} | |
pure string QParseGrabCases(RET, ARGS...)() { | |
string ret; | |
enum members = EnumMembers!RET; | |
foreach(i, arg; ARGS) { | |
ret ~= " case \"" ~ arg ~ "\":\n"; | |
ret ~= " return " ~ members[i].stringof ~ ";\n"; | |
} | |
return ret; | |
} | |
mixin template QParseOtherBitwise(string name, RET, ARGS...) if ((EnumMembers!RET).length-2 == ARGS.length) { | |
mixin("""size_t " ~ name ~ "(string text, ref string other) { | |
size_t ret; | |
string[] stes = text.split(\",\"); | |
foreach(ste; stes) { | |
switch(ste) { | |
" ~ QParseGrabCasesBitwise!(RET, ARGS) ~ " | |
case \"Other\": | |
continue; | |
default: | |
other = ste; | |
ret |= RET.Other; | |
break; | |
} | |
} | |
return ret; | |
}"""); | |
} | |
pure string QParseGrabCasesBitwise(RET, ARGS...)() { | |
string ret; | |
enum members = (EnumMembers!RET)[1 .. $]; | |
foreach(i, arg; ARGS) { | |
ret ~= " case \"" ~ arg ~ "\":\n"; | |
ret ~= " ret |= " ~ members[i].stringof ~ ";\n"; | |
ret ~= " break;\n"; | |
} | |
return ret; | |
} |
Because I love templates, I created mixin templates called QParse, QParseOther and QParseOtherBitwise. These had "business rules" mixed in it e.g. a bitwised enum for RET must include None and Other in it.
Code like the top example could then be replaced by:
mixin QParseOther!("yesNoOther", YesNoOther, "Yes", "No");
One line instead of like 15 lines. I really don't feel like a code monkey anymore.
This blog post really does just show how much I love D's templates and compile time functionality.
No comments:
Post a Comment