Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala dispatch example

Tags:

scala

I'm a Java engineer who's been slowly learning Scala recently. I've come across some sample code using Dispatch to make a simple GET request:

val request = url("http://somesite.com")
val result = Http( request OK as.String)

The problem is... I don't quite get what's going on here. First, is Http a class? or a method? Second, what's up with the parameters passed to it? I thought maybe we were passing three arguments, with Scala allowing us to omit commas. But when I tried adding commas, I got a compilation error, so that can't be right.

I'm sure this makes sense to someone fluent in Scala, but I'm not there yet and it's holding me up. I've tried looking for documentation online, but have found nothing helpful.

like image 686
Dave Taubler Avatar asked Jan 26 '15 02:01

Dave Taubler


1 Answers

url is (essentially) a method that returns a Req object. So request has type Req.

Http is a class with a companion object that has a few overloads of the apply method. So when you see:

Http(request OK as.String)

It is actually syntactic sugar for:

Http.apply(request OK as.String)

Ok, so what's going on inside apply? It appears as though a method named OK is being called on request. But looking through the API Docs, you may notice there is no such method OK for the type Req. There is, however, a class called RequestHandlerTupleBuilder, which does have such a method. And there is an implicit conversion defined in the dispatch package:

implicit def implyRequestHandlerTuple(builder: Req) =
    new RequestHandlerTupleBuilder(builder)

What's happening here is that when you call request OK, the compiler sees that request does not have an OK method. So it then looks for possible implicit methods that accept Req as a parameter and return types to do have such a method. The above method is the implicit it finds, so the Req is implicitly converted to a RequestHandlerTupleBuilder.

Now let's look at the signature of OK:

def OK [T](f: Response => T): (Request, OkFunctionHandler[T])

It accepts a function as a parameter. In particular, a function that accepts a Response as a parameter, and returns some other type T. In this case, such a function is as.String that has type Response => String. OK will then return a Request tupled with an OkFunctionHandler[T].

This tells me that the overload of apply we're calling is this one:

def apply[T](pair: (Request, AsyncHandler[T])): Future[T]

(OkFunctionHandler extends AsyncHandler)

Looking it all in a slightly more java-like style and with type annotations, you have:

val request: Req = url("http://somesite.com")
val result: Future[String] = Http.apply(request.OK(as.String))

Using only explicit calls, it would look more like:

val result: Future[String] = 
    Http.apply(implyRequestHandlerTuple(request).OK(as.String))

In short, there is only one parameter being passed to Http.apply, it's just using a point-free style to call other methods within.

like image 138
Michael Zajac Avatar answered Sep 28 '22 19:09

Michael Zajac