Last active
October 24, 2018 21:36
-
-
Save MiloXia/e12de140f8a5e31b87a443f9b78171a5 to your computer and use it in GitHub Desktop.
Scala Conditional Compilation
This file contains hidden or 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 scala.language.higherKinds | |
object Conditions { | |
//based on: An Introduction to Functional Programming Through Lambda Calculus | |
trait BOOL { | |
type body[e1 <: E, e2 <: E, E] <: E //select: (E, E) => E | |
} | |
trait TRUE extends BOOL { | |
type body[e1 <: E, e2 <: E, E] = e1 //true = select_first | |
} | |
trait FALSE extends BOOL { | |
type body[e1 <: E, e2 <: E, E] = e2 //false = select_second | |
} | |
trait COND[e1 <: E, e2 <: E, E, c <: BOOL] { | |
type r = c#body[e1, e2, E] //cond = λe1.λe2.λc.((c e1) e2) | |
} | |
//let E = BOOL, IF[c, e1, e2] just return TRUE or FALSE | |
//type IF[c <: BOOL, e1 <: BOOL, e2 <: BOOL] = COND[e1, e2, BOOL, TRUE]#r | |
//implicitly[IF[TRUE, FALSE, TRUE] =:= TRUE] | |
//not = λx.(((cond false) true) x) | |
type NOT[x <: BOOL] = COND[FALSE, TRUE, BOOL, x]#r | |
//and = λx.λy.(((cond y) false) x) | |
type AND[x <: BOOL, y <: BOOL] = COND[y, FALSE, BOOL, x]#r | |
//or = λx.λy.(((cond true) y) x) | |
type OR[x <: BOOL, y <: BOOL] = COND[TRUE, y, BOOL, x]#r | |
type ![x <: BOOL] = NOT[x] | |
type ||[x <: BOOL, y <: BOOL] = OR[x, y] | |
type &&[x <: BOOL, y <: BOOL] = AND[x, y] | |
//test | |
implicitly[ TRUE && FALSE || NOT[FALSE] =:= TRUE] | |
} | |
object CondCompilation { | |
//based on blog: https://michid.wordpress.com/2008/10/29/meta-programming-with-scala-conditional-compilation-and-loop-unrolling/ | |
import Conditions._ | |
def _IF[B] = null.asInstanceOf[B] | |
//TRUE => Include | |
object Include { | |
def apply(block: => Unit) { | |
block | |
} | |
} | |
//FALSE => Exclude | |
object Exclude { | |
def apply(block: => Unit) { } | |
} | |
implicit def include(t: TRUE) = Include | |
implicit def exclude(f: FALSE) = Exclude | |
} | |
object IfDefTest { | |
import Conditions._ | |
import CondCompilation._ | |
type LOG = TRUE | |
type ERR = TRUE | |
type WARN = FALSE | |
type DEV = TRUE | |
def errTest() { | |
_IF[LOG && ERR] { | |
println("err") | |
} | |
} | |
def warnTest() { | |
_IF[LOG && WARN] { | |
println("warn") | |
} | |
} | |
def main(args: Array[String]) { | |
errTest() | |
warnTest() | |
_IF[DEV] { | |
println("dev") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment