O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
Typed Channels                              and                           Macros                           Dr. Roland Kuhn...
The Problem                  someActor ! CommandOnesöndag 10 februari 13
The Problem                  trait Command                  case class CommandOne(param: String) extends Command          ...
The Vision                           someActor <-!- CommandOne(”msg”)                        because the other does not co...
But How?                        • ActorRef must know about message types                          – Actor type must be par...
And the replies?                            val f: Future[Response] =                        someActor <-?- CommandOne(”he...
And How This?                        • ActorRef must know reply types                          – Actor must be parameteriz...
No Type Pollution                        • Generic Filter/Transform Actors                          – accept management co...
Actors Do Compose                         msg -?-> firstActor -?-> secondActor -!-> client                        msg -?->...
The Result:söndag 10 februari 13
Type-Safe Composability                             of                        Actor Systemssöndag 10 februari 13
Relation to π-calculus                        • Actors are composite processes                        • Actor types are st...
That was the                            Eloi world                        Now we’re going to visit the Morlockssöndag 10 f...
The Implementation                        • Tagged type union with                          :+:[(In, Out), ChannelList] <:...
How to Declare it?                  class OpinionatedEcho extends Actor                      with Channels[TNil, (String, ...
First Problem: Lambdas                        • Type-checker transforms lambda before the                          macro c...
First Problem: Lambdas                        private class Behaviorist[-R, Ch: ru.TypeTag](                            wr...
The Gory Details                        def impl[LUB, ReplyChannels <: ChannelList,                            MsgTChan <:...
The Gory Details                        trait Channels[P <: ChannelList, C <: ChannelList] {                          this...
Sample Type Calculation                    final def missingChannels(u: Universe)(                        channels: u.Type...
How to Return a Type                        def impl[..., ReplyChannels <: ChannelList, ...]                            (c...
Sharing Code with Runtime                        final def x(u: Universe)(list: u.Type, msg: u.Type)                      ...
How to test it?                        def mkToolbox(compileOptions: String = "")                          : ToolBox[_ <: ...
How to test it?                    intercept[ToolBoxError] {                        eval("""                             i...
get it and learn more                           http://akka.io                        http://letitcrash.com               ...
E0Fsöndag 10 februari 13
Próximos SlideShares
Carregando em…5
×

Akka typed-channels

2.566 visualizações

Publicada em

These slides are for my presentation at North-East Scala Symposium 2013 in Philadelphia, see http://nescala.org. The video is available at http://www.youtube.com/watch?v=PCk2SHufw3E

Publicada em: Educação
  • Seja o primeiro a comentar

Akka typed-channels

  1. 1. Typed Channels and Macros Dr. Roland Kuhn @rolandkuhnsöndag 10 februari 13
  2. 2. The Problem someActor ! CommandOnesöndag 10 februari 13
  3. 3. The Problem trait Command case class CommandOne(param: String) extends Command someActor ! CommandOnesöndag 10 februari 13
  4. 4. The Vision someActor <-!- CommandOne(”msg”) because the other does not compilesöndag 10 februari 13
  5. 5. But How? • ActorRef must know about message types – Actor type must be parameterized • Message type is verified against thatsöndag 10 februari 13
  6. 6. And the replies? val f: Future[Response] = someActor <-?- CommandOne(”hello”) because the compiler knowssöndag 10 februari 13
  7. 7. And How This? • ActorRef must know reply types – Actor must be parameterized with them • Reply types are extracted at call sitesöndag 10 februari 13
  8. 8. No Type Pollution • Generic Filter/Transform Actors – accept management commands – pass on generic other type • Using just one type is not enough! • Need to use type unions and allow multiple possible reply types for one inputsöndag 10 februari 13
  9. 9. Actors Do Compose msg -?-> firstActor -?-> secondActor -!-> client msg -?-> someService -*-> (_ map httpOk) -!-> client Process wiring from the outsidesöndag 10 februari 13
  10. 10. The Result:söndag 10 februari 13
  11. 11. Type-Safe Composability of Actor Systemssöndag 10 februari 13
  12. 12. Relation to π-calculus • Actors are composite processes • Actor types are structural, not nominal • wiring A͡B can be done situationally http://doc.akka.io/ see Typed Channelssöndag 10 februari 13
  13. 13. That was the Eloi world Now we’re going to visit the Morlockssöndag 10 februari 13
  14. 14. The Implementation • Tagged type union with :+:[(In, Out), ChannelList] <: ChannelList • Value class ChannelRef[…](val a: ActorRef) • Actor mixin Channels[…] • WrappedMessage[…, LUB](val m: LUB) • ops desugar to tell/ask after type checksöndag 10 februari 13
  15. 15. How to Declare it? class OpinionatedEcho extends Actor with Channels[TNil, (String, String) :+: TNil] { channel[String] { (str, sender) ⇒ sender <-!- str } // or channel[String] { case (”hello”, sender) ⇒ sender <-!- ”world” case (x, sender) ⇒ sender <-!- s”dunno: $x” } } “sender” will accept only String messagessöndag 10 februari 13
  16. 16. First Problem: Lambdas • Type-checker transforms lambda before the macro call – pattern matches or PartialFunction literals generate checks depending on static type info • Behavior is not an argument to “channels” • macro only emits object with right “apply”söndag 10 februari 13
  17. 17. First Problem: Lambdas private class Behaviorist[-R, Ch: ru.TypeTag]( wrapped: Boolean) extends (R ⇒ Unit) { // ... def apply(recv: R): Unit = { val tt = ru.typeTag[Ch] behavior ++= ( for (t ← inputChannels(ru)(tt.tpe)) yield tt.mirror.runtimeClass(t.widen) -> ff(recv)) } } calling channels[_] registers the behaviorsöndag 10 februari 13
  18. 18. The Gory Details def impl[LUB, ReplyChannels <: ChannelList, MsgTChan <: ChannelList, MsgT: c.WeakTypeTag, MyCh <: ChannelList: c.WeakTypeTag, ParentCh <: ChannelList: c.WeakTypeTag]( c: Context { type PrefixType = Channels[ParentCh, MyCh] }): c.Expr[(Nothing ⇒ Unit)] = { // some type calculations happen here val prepTree = reify(...) reify { prepTree.splice c.prefix.splice.behaviorist[ (MsgT, ChannelRef[ReplyChannels]) ⇒ Unit, MsgT]( bool(c, false).splice)(universe.typeTag[MsgT]) } }söndag 10 februari 13
  19. 19. The Gory Details trait Channels[P <: ChannelList, C <: ChannelList] { this: Actor ⇒ def channel[T]: (Nothing ⇒ Unit) = macro macros.Channel.impl[Any, ChannelList, ChannelList, T, C, P] def behaviorist[R, Ch: ru.TypeTag](wrapped: Boolean) : (R ⇒ Unit) = new Behaviorist[R, Ch](wrapped) // ... }söndag 10 februari 13
  20. 20. Sample Type Calculation final def missingChannels(u: Universe)( channels: u.Type, required: List[u.Type]): List[u.Type] = { import u._ // making the top-level method recursive blows up the compiler def rec(ch: Type, req: List[Type]): List[Type] = { ch match { case TypeRef(_, _, TypeRef(_, _, in :: _) :: tail :: Nil) ⇒ rec(tail, req filterNot (_ <:< in)) case last ⇒ req filterNot (_ <:< last) } } rec(channels, required) }söndag 10 februari 13
  21. 21. How to Return a Type def impl[..., ReplyChannels <: ChannelList, ...] (c: Context): c.Expr[(Nothing ⇒ Unit)] = { // calculate “channels: u.Type” and then: implicit val ttReplyChannels = c.TypeTag[ReplyChannels](channels) reify { ...[(..., ...[ReplyChannels]) ⇒ ..., ...]... } } “reify” picks up TypeTags and uses their .tpesöndag 10 februari 13
  22. 22. Sharing Code with Runtime final def x(u: Universe)(list: u.Type, msg: u.Type) : List[u.Type] = { val imp = u.mkImporter(ru) val tpeReplyChannels = imp.importType(ru.typeOf[ReplyChannels[_]]) val tpeTNil = imp.importType(ru.typeOf[TNil]) // ... } otherwise there will be weird exceptionssöndag 10 februari 13
  23. 23. How to test it? def mkToolbox(compileOptions: String = "") : ToolBox[_ <: scala.reflect.api.Universe] = { val m = scala.reflect.runtime.currentMirror m.mkToolBox(options = compileOptions) } def eval(code: String, compileOptions: String = "-cp akka-actor/target/classes:akka-channels/target/classes") : Any = { val tb = mkToolbox(compileOptions) tb.eval(tb.parse(code)) }söndag 10 februari 13
  24. 24. How to test it? intercept[ToolBoxError] { eval(""" import akka.channels._ import ChannelSpec._ implicit val c = new ChannelRef[TNil](null) new ChannelRef[(A, C) :+: TNil](null) <-!- B """) }.message must include( "target ChannelRef does not support messages of " + "types akka.channels.ChannelSpec.B.type")söndag 10 februari 13
  25. 25. get it and learn more http://akka.io http://letitcrash.com http://typesafe.comsöndag 10 februari 13
  26. 26. E0Fsöndag 10 februari 13

×