Hi Elliot, the reason is not the type parameter directly, but the `: ClassTag` context bound which introduces an implicit parameter list to your method. So, after unfolding this syntactic sugar your withActor method basically looks like this:
def withActor[A <: Actor](message: Any)(implicit ev: ClassTag[A]): Directive1[Future[Any]] So, then if you don't use `apply`, the compliler thinks the block you pass to `withActor` is an attempt to pass the implicit parameter explicitly. We have the same problem internally for some directives. You might want to look at two different kind of approaches to that: * `MarshallingDirectives.entity(as[T])` pattern, will move the implicit parameter inside the first value * `HeaderDirectives.headerValueByType` which uses a magnet as explained in http://spray.io/blog/2012-12-13-the-magnet-pattern/ Johannes On Thursday, February 9, 2017 at 5:18:28 PM UTC+1, Elliot Wright wrote: > > I started out with, quite honestly, a stupid idea. However, once I started > it I wanted to see it through to learn from it and hopefully gain some > insight into how you might actually write a directive. I've discovered a > few things in the process, but have no idea why these things are the way > they are (I'm quite new to Scala, so this may actually be more of a general > Scala question that just happens to be relevant to Akka HTTP). > > So I'd seen that some people in the past had used the "actor-per-request" > pattern with things like Spray. In many ways this made a lot of sense to > me, because in doing so it provides a nice entrypoint into using other > actors in a request, as your action-handling code can actually react to > messages appropriately. I still don't really know if that is a good idea or > not, it's probably entirely unnecessary, but for now we can just assume I'm > also trying to learn a little about actors. > > With all of that in mind, I wanted to make a directive to reduce some of > the boilerplate in creating an actor, and asking it a message. My first > attempt looked something like this: > > def withActor[A <: Actor: ClassTag](message: Any): Directive1[Future[Any]] = { > provide(system.actorOf(Props[A]) ? message) > } > > > Now, I know that this thing is pretty much completely pointless, because > it doesn't even take that much to just do this yourself in reality. I had > planned to add some more to this, like moving the onComplete call into it > or something. Again though, this is just for learning now really. > > To be honest, this approach actually does work now I've figured out this > last detail that eluded me for so long. I actually have to use it something > like this: > > val route: Route = > pathSingleSlash { > get { > withActor[RequestHandler](RequestHandler.Handle).apply { future => > onComplete(future) { > case Success(result: RequestHandler.Result) => complete(result.data) > case _ => complete(StatusCodes.InternalServerError) > } > } > } > } > > > So, the .apply there is necessary - and this is what is confusing me right > now. It seems to be the type parameter being there that is causing this. It > also happens if you try add implicit parameters in a separate argument list > too. In the case of the implicit arguments I can at least understand why, > because the block following the function call would be treated as the bit > inside the curly braces, so calling apply makes it a bit more explicit. In > this case though, I don't know why I have to call apply. Can anybody > explain? > -- >>>>>>>>>> Read the docs: http://akka.io/docs/ >>>>>>>>>> Check the FAQ: >>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html >>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user --- You received this message because you are subscribed to the Google Groups "Akka User List" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.
