Last active
July 5, 2019 13:26
-
-
Save aliak00/fcdd4fa7512035405bb7015cf6d8016f to your computer and use it in GitHub Desktop.
Comparing functions in wrappers
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
import std.stdio; | |
template isTransformedWrapper(W) { | |
enum isTransformedWrapper = is(W : TrasformedWrapper!T, T...); | |
} | |
struct Wrapped(T) { | |
T value; | |
} | |
auto wrap(T)(T value) { | |
return Wrapped!(T)(value); | |
} | |
struct TrasformedWrapper(alias fun, T, U) { | |
alias Fun = fun; | |
T originalValue; | |
U value; | |
} | |
auto transform(alias fun, T)(Wrapped!T w) { | |
alias U = typeof(fun(w.value)); | |
return TrasformedWrapper!(fun, T, U)(w.value, fun(w.value)); | |
} | |
/* | |
template transformer(WT, alias fallback = null) { | |
static if (isTransformedWrapper!WT) { | |
alias transformer = WT.Fun; | |
} else { | |
alias transformer = fallback; | |
} | |
} | |
*/ | |
enum isSame(alias f0, alias f1) = __traits(isSame, f0, f1); | |
auto ref resolveTrasnformedData( | |
alias receivedData, | |
alias isTransformedType, | |
alias isTransformOk, | |
alias transformFn, | |
alias untransformFn, | |
)() { | |
alias ReceivedType = typeof(receivedData); | |
enum identifier = __traits(identifier, receivedData); | |
static if (!isTransformedType!ReceivedType) { | |
writeln(identifier, " data not tranformed, transforming"); | |
return transformFn(receivedData); | |
} else static if (isTransformOk!ReceivedType) { | |
writeln(identifier, " data tranformed, and transformer ok, doing nothing"); | |
return receivedData; | |
} else { | |
writeln(identifier, " data transformed, but transformer not ok, transforming"); | |
return transformFn(untransformFn(receivedData)); | |
} | |
} | |
auto algorithm(alias fun, W0, W1)(W0 w0, W1 w1) { | |
alias isTransformOk(T) = isSame!(T.Fun, fun); | |
alias transform = (data) => .transform!fun(data); | |
alias untransform = (data) => data.originalValue.wrap; | |
auto t0 = resolveTrasnformedData!(w0, isTransformedWrapper, isTransformOk, transform, untransform); | |
auto t1 = resolveTrasnformedData!(w1, isTransformedWrapper, isTransformOk, transform, untransform); | |
// writeln("## ", a0); | |
/* | |
write("t0: "); | |
static if (!isTransformedWrapper!W0) { | |
write("needs transform"); | |
auto t0 = w0.transform!fun; | |
} else static if (isSame!(W0.Fun, fun)) { | |
write("transformed correctly"); | |
auto t0 = w0; | |
} else { | |
write("transformed incorrectly"); | |
auto t0 = w0.originalValue.wrap.transform!fun; | |
} | |
write(", t1: "); | |
static if (!isTransformedWrapper!W1) { | |
write("needs transform"); | |
auto t1 = w1.transform!fun; | |
} else static if (isSame!(W1.Fun, fun)) { | |
write("transformed correctly"); | |
auto t1 = w0; | |
} else { | |
write("transformed incorrectly"); | |
auto t1 = w0.originalValue.wrap.transform!fun; | |
} | |
writeln; | |
*/ | |
/* | |
static if (isTransformedWrapper!W0 && isTransformedWrapper!W1) { | |
// Both already transformed | |
static if (isSame!(W0.Fun, fun) && isSame!(W1.Fun, fun)) { | |
// They both have the same transformer | |
writeln("both wrapped, no transforms needed"); | |
auto t0 = w0; | |
auto t1 = w1; | |
} else { | |
static if (isSame!(W0.Fun, fun)) { | |
writeln("both wrapped, w0.fun ok, w1 needs transform"); | |
auto t0 = w0; | |
auto t1 = w1.originalValue.wrap.transform!fun; | |
} else static if (isSame!(W1.Fun, fun)) { | |
writeln("both wrapped, w0 needs transform, w1.fun ok"); | |
auto t0 = w0.originalValue.wrap.transform!fun; | |
auto t1 = w1; | |
} else { | |
writeln("both wrapped, w0 needs transform, w1 needs transform"); | |
auto t0 = w0.originalValue.wrap.transform!fun; | |
auto t1 = w1.originalValue.wrap.transform!fun; | |
} | |
} | |
} else static if (isTransformedWrapper!W0) { | |
// Only w0 is transformed | |
static if (isSame!(W0.Fun, fun)) { | |
writeln("w0 wrapped, w0.fun ok"); | |
auto t0 = w0; | |
} else { | |
writeln("w0 wrapped, w0 needs transform"); | |
auto t0 = w0.originalValue.wrap.transform!fun; | |
} | |
auto t1 = w1; | |
} else static if (isTransformedWrapper!W1) { | |
// Only w1 is transformed | |
auto t0 = w0; | |
static if (isSame!(W1.Fun, fun)) { | |
writeln("w1 wrapped, w1.fun ok"); | |
auto t1 = w1; | |
} else { | |
writeln("w1 wrapped, w1 needs transform"); | |
auto t1 = w1.originalValue.wrap.transform!fun; | |
} | |
} else { | |
// Neither are transformed types | |
writeln("neither wrapped, transforming both"); | |
auto t0 = w0.transform!fun; | |
auto t1 = w1.transform!fun; | |
} | |
*/ | |
// Perform algorithm on transformed values. | |
return t0.value + t1.value; | |
} | |
int f(int a) { | |
return a + a + a; | |
} | |
void main() { | |
alias x2 = (a) => a * 2; | |
alias x3 = (a) => a * 3; | |
auto a = 2.wrap; | |
auto tx2 = a.transform!x2; | |
auto tx3 = a.transform!x3; | |
tx2.writeln; | |
tx3.writeln; | |
writeln("x2(a, a)"); | |
algorithm!x2(a, a).writeln; | |
writeln("x3(a, a)"); | |
algorithm!x3(a, a).writeln; | |
writeln("x2(tx2, tx2)"); | |
algorithm!x2(tx2, tx2).writeln; | |
writeln("x3(tx2, tx2)"); | |
algorithm!x3(tx2, tx2).writeln; | |
writeln("x2(tx3, tx3)"); | |
algorithm!x2(tx3, tx3).writeln; | |
writeln("x3(tx3, tx3)"); | |
algorithm!x3(tx3, tx3).writeln; | |
writeln("x2(tx2, tx3)"); | |
algorithm!x2(tx2, tx3).writeln; | |
writeln("x2(tx2, tx3)"); | |
algorithm!x3(tx2, tx3).writeln; | |
writeln("x2(a.transform!f, a)"); | |
algorithm!f(a.transform!f, a).writeln; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment