Skip to content

Instantly share code, notes, and snippets.

@sam
Created February 12, 2016 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sam/a7347ee19b94d0cdb122 to your computer and use it in GitHub Desktop.
Save sam/a7347ee19b94d0cdb122 to your computer and use it in GitHub Desktop.
Not sure how to create a macro that would allow me to extend a trait and have generated code.
// Example actor:
class EchoActor extends Actor {
def receive = {
case message => context.sender ! message
}
}
// I want to be able to write:
object EchoActor extends ActorGenerator0
// And for that to be equivilent to:
object EchoActor extends {
val counter = new AtomicLong(1)
def apply()(implicit factory: ActorRefFactory): ActorRef =
factory.actorOf(Props(new EchoActor(), name = "echo-%d".format(counter.getAndIncrement)))
}
// So that I can:
val echo = EchoActor()
// The real point being Actors with constructor arguements:
class ArgumentativeActor(prefix: String) extends Actor {
def receive = {
case message => context.sender ! "%s: %s!".format(prefix, message)
}
}
object ArgumentativeActor extends ActorGenerator1
// And be able to:
val argumentative = ArgumentativeActor("NO")
// And it be type-safe, because companionClass is used, and it's constructor arguments used to build:
// def apply(prefix: String)(implicit factory: ActorRefFactory): ActorRef =
// factory.actorOf(Props(new ArgumentativeActor(prefix), name = "argumentative-%d".format(counter.getAndIncrement))
// Macro:
object ActorGenerator {
implicit def generatorOf[T <: Actor]: Class[ActorGenerator0[T]] = macro generatorOfImpl[T]
def generatorOfImpl[T <: Actor : c.WeakTypeTag](c: Context): c.Expr[Class[ActorGenerator0[T]]] = {
import c.universe._
val tpe = weakTypeOf[T]
val name = tpe.typeSymbol.name.toString
c.Expr[Class[ActorGenerator0[T]]] { q"""
abstract class ActorGenerator0[$tpe] {
import akka.actor._
def name = "%s-%d".format($name, counter.getAndIncrement())
def props() = Props(new $tpe())
def apply()(implicit factory: ActorRefFactory): ActorRef = factory.actorOf(props, name)
}
""" }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment