Hi, all,
I just published a new library template.scala, designed to create whitebox inline functions, providing ability similar to C++ template.
The template.scala library is similar to SIP-28 inline
except template.scala provides whiteboxity.
scalaVersion := "2.12.1" // or "2.11.8"
resolvers += "Sonatype" at "https://oss.sonatype.org/content/groups/public"
libraryDependencies += "com.thoughtworks.template" %% "template" % "latest.release" % Provided
addCompilerPlugin("org.scalameta" % "paradise" % "3.0.0-M7" cross CrossVersion.patch)
A template function is created with a @template
annotation.
@template
def max(x: Any, y: Any) = {
if (x > y) x else y
}
Unlike normal functions, a template function will not be type-checked until using it. Thus it does not raise a type error on x > y
because the real types of x
and y
have not been determinated.
val i: Int = max(1, 2)
val d: Double = max(8.0, 0.5)
The max
function will be type-checkd and inlined whenever being invoked.
If the type of x
does not support >
method, it does not compile:
val s: Symbol = max('foo, 'bar)
<macro>:1: value > is not a member of Symbol
def max(x: Any, y: Any) = if (x > y) x else y
^
Template functions can be recursive, as long as the number of calls are finite and can be determinated at compile-time.
The following code creates a heterogeneous list.
sealed trait HList {
final def ::(head: Any): head.type :: this.type = {
new (head.type :: this.type)(head, this)
}
}
case object HNil extends HList
final case class ::[Head, Tail <: HList](head: Head, tail: Tail) extends HList {
def apply(i: 0): head.type = {
head
}
@template
def apply(i: Int with Singleton): Any = {
tail(i - 1)
}
}
Then you can index elements in the HList via template function apply
.
val hlist = "foo" :: 1 :: false :: HNil
val s: String = hlist(0)
val i: Int = hlist(1)
val b: Boolean = hlist(2)
hlist(3) // Compile error
Note that the above HList
code need TypeLevel Scala and -Yliteral-types
flag.
@template
functions always inline, never sharing similar implementations like C++ templates.@template
functions do not support type parameters.- Recursive
@template
functions must be resolved at compile-time.