Created
April 5, 2018 16:42
-
-
Save eernstg/e6351d655334455c511288345c5fbaec to your computer and use it in GitHub Desktop.
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
bool b = false; | |
void doWork(int i) => print("Do work ($i)"); | |
void bailOut(int i) => print("Bail out ($i)"); | |
void acquire() => print("Acquire the resource"); | |
void release() => print("Release the resource"); | |
// Consider: We want to simplify the following control flow. | |
void foo(List<bool> b) { | |
print("---------------------"); | |
acquire(); | |
doWork(0); | |
if (b[0]) { | |
bailOut(0); | |
release(); | |
return; | |
} | |
doWork(1); | |
if (b[1]) { | |
bailOut(1); | |
release(); | |
return; | |
} | |
doWork(2); | |
if (b[2]) { | |
bailOut(2); | |
release(); | |
return; | |
} | |
doWork(3); | |
release(); | |
doWork(4); | |
} | |
// Simplification using a local function to abstract out common elements. | |
// Problem: We seem to want non-local returns. Also, we create closures | |
// for each `bailOut`, and they will be allocated even if left unused. | |
void foo1(List<bool> b) { | |
bool failed(bool b, void then()) { | |
if (!b) return b; | |
then(); | |
release(); | |
return true; // "Should" have returned from `foo1`. | |
} | |
print("---------------------"); | |
acquire(); | |
doWork(0); | |
if (failed(b[0], () { bailOut(0); })) return; | |
doWork(1); | |
if (failed(b[1], () { bailOut(1); })) return; | |
doWork(2); | |
if (failed(b[2], () { bailOut(2); })) return; | |
doWork(3); | |
release(); | |
doWork(4); | |
} | |
// Simplification purely via control flow reorganization. | |
void foo2(List<bool> b) { | |
print("---------------------"); | |
acquire(); | |
doWork(0); | |
if (b[0]) bailOut(0); else { | |
doWork(1); | |
if (b[1]) bailOut(1); else { | |
doWork(2); | |
if (b[2]) bailOut(2); else { | |
doWork(3); | |
doWork(4); // Work 4 and release can be swapped: independent. | |
} | |
} | |
} | |
release(); | |
} | |
void run(void f(List<bool> b)) { | |
f([false,false,false]); | |
f([false,false,true]); | |
f([false,true,false]); | |
f([true,false,false]); | |
} | |
main() { | |
run(foo); | |
print(""); | |
run(foo2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment