Skip to content

Instantly share code, notes, and snippets.

@alphaKAI
Last active December 25, 2015 10:25
Show Gist options
  • Save alphaKAI/96e2b34cec66d3a670ea to your computer and use it in GitHub Desktop.
Save alphaKAI/96e2b34cec66d3a670ea to your computer and use it in GitHub Desktop.
import std.stdio,
std.typetuple;
alias TypeTuple!(
byte, ubyte, short,
ushort, int, uint, long,
ulong, float, double, real) primitiveTypes;
Caluculatable!T newCaluculatable(T)(T v){
return Caluculatable!T(v);
}
struct Caluculatable(T){
enum isCaluculatableValue;
private T value;
alias value this;
this(T v){
value = v;
}
}
static bool isCaluculatable(T)(T l){
return isCaluculatable!T;
}
static bool isCaluculatable(T)(){
if(__traits(hasMember, T, "isCaluculatableValue"))
return true;
else
foreach(i, U; primitiveTypes)
if(typeid(U) is typeid(T))
return true;
return false;
}
static string magic(string f, string o, string pred = null){
return
"auto " ~ f ~ "(A, B)(A a, B b) if(isCaluculatable!A && isCaluculatable!B){"
~ pred
~ "return a" ~ o ~ "b;"
~ "}"
~ "auto " ~ f ~ "(A)(A x) if(isCaluculatable!A){"
~ "return (A y) => " ~ f ~ "(x, y);"
~ "}"
~ "auto " ~ f ~ "(A)(){"
~ "return (A x) => (A y) => " ~ f ~ "(x, y);"
~ "}";
}
class ZeroDivisionError: Error{
this(string msg){
super(msg);
}
}
mixin(magic("add", "+"));
mixin(magic("sub", "-"));
mixin(magic("mul", "*"));
mixin(magic("div", "/", `if(b == 0) throw new ZeroDivisionError("divided by 0");`));
void main(){
add(newCaluculatable(1),
newCaluculatable(2)).writeln;
assert(add(1, 2) == add(newCaluculatable(1), newCaluculatable(2)));
assert(add(1, 2) == add(Caluculatable!int(1), Caluculatable!int(2)));
add(newCaluculatable(3),
newCaluculatable(4)).writeln;
assert(add(3, 4) == add(newCaluculatable(3), newCaluculatable(4)));
assert(add(3, 4) == add(Caluculatable!int(3), Caluculatable!int(4)));
sub(newCaluculatable(4),
newCaluculatable(2)).writeln;
assert(sub(4, 2) == sub(newCaluculatable(4), newCaluculatable(2)));
assert(sub(4, 2) == sub(Caluculatable!int(4), Caluculatable!int(2)));
mul(newCaluculatable(4),
newCaluculatable(2)).writeln;
assert(mul(4, 2) == mul(newCaluculatable(4), newCaluculatable(2)));
assert(mul(4, 2) == mul(Caluculatable!int(4), Caluculatable!int(2)));
div(newCaluculatable(100),
newCaluculatable(2)).writeln;
assert(div(100, 2) == div(newCaluculatable(100), newCaluculatable(2)));
assert(div(100, 2) == div(Caluculatable!int(100), Caluculatable!int(2)));
try{
div(newCaluculatable(100),
newCaluculatable(0));
} catch(ZeroDivisionError e){
writeln("[Catch a ZeroDivisionError] : Can not divided by zero");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment