Scala пример отправки
Я инженер Java, который недавно изучал Scala. Я столкнулся с некоторым примером кода с помощью Dispatch, чтобы сделать простой запрос GET:
val request = url("http://somesite.com")
val result = Http( request OK as.String)
Проблема в том, что... Я не совсем понимаю, что происходит здесь. Во-первых, Http класс? или метод? Во-вторых, что с переданными параметрами? Я думал, может быть, мы пропустили три аргумента, Scala позволили нам пропустить запятые. Но когда я попытался добавить запятые, у меня была ошибка компиляции, поэтому это не может быть прав.
Я уверен, что это имеет смысл для кого-то свободного в Scala, но я еще не там, и это держит меня. Я пробовал искать документацию в Интернете, но ничего не нашел.
Ответы
Ответ 1
Здесь (болезненно) явная версия со всем выведенным синтаксическим сахаром:
import dispatch.{ Defaults, Http, Req, as, implyRequestHandlerTuple, url }
import scala.concurrent.Future
val request: Req = url.apply("http://somesite.com")
val result: Future[String] =
Http.apply(
implyRequestHandlerTuple(request).OK[String](as.String)
)(Defaults.executor)
url
- это одноэлементный объект с методом apply
, который возвращает экземпляр класса case Req
. Http
также является одноэлементным объектом, а также имеет метод apply
. Http
apply
принимает два списка параметров: первый принимает один параметр Req
, а второй принимает контекст выполнения (который вы можете представить как Scala версия Java Executor
).
implyRequestHandlerTuple
является неявным методом. Req
не имеет метода OK
, но компилятор знает, что класс RequestHandlerTupleBuilder
(и что он принимает соответствующие аргументы - в этом случае - функцию от Response
до некоторого типа), поэтому в оригинальная версия автоматически применяет этот метод для преобразования из Req
.
Наконец, as
представляет собой пакет, содержащий объект String
singleton. Этот объект расширяет Response => String
(что является более синтаксическим сахаром для Function1[Response, String]
. Наш метод OK
искал функцию с Response
, поэтому мы там хорошо.
В итоге у вас есть Future[String]
. Есть много других мест, чтобы читать о фьючерсах, поэтому я не буду вдаваться в подробности здесь, но вкратце это значение может быть либо неудовлетворенным ( т.е. вы все еще ожидаете результата) или удовлетворены сбоем (в случае сетевой ошибки и т.д.) или удовлетворены (в этом случае он будет содержать тело ответа).
Ответ 2
url
- (по существу) метод, возвращающий объект Req
. Итак, request
имеет тип Req
.
Http
- это класс с сопутствующим объектом, который имеет несколько перегрузок метода apply
. Поэтому, когда вы видите:
Http(request OK as.String)
На самом деле это синтаксический сахар для:
Http.apply(request OK as.String)
Хорошо, так что происходит внутри apply
? Похоже, что на request
вызывается метод с именем OK
. Но просматривая API Docs, вы можете заметить, что такого типа OK
для типа Req
нет. Однако существует класс под названием RequestHandlerTupleBuilder
, который имеет такой метод. И есть неявное преобразование, определенное в пакете dispatch
:
implicit def implyRequestHandlerTuple(builder: Req) =
new RequestHandlerTupleBuilder(builder)
Что происходит в том, что при вызове request OK
компилятор видит, что request
не имеет метода OK
. Поэтому он ищет возможные неявные методы, которые принимают Req
как параметр и возвращаемые типы, чтобы иметь такой метод. Вышеуказанный метод является неявным, который он находит, поэтому Req
неявно преобразуется в RequestHandlerTupleBuilder
.
Теперь посмотрим на подпись OK
:
def OK [T](f: Response => T): (Request, OkFunctionHandler[T])
Он принимает функцию как параметр. В частности, функция, которая принимает параметр Response
в качестве параметра и возвращает другой тип T
. В этом случае такая функция as.String
имеет тип Response => String
. OK
затем вернет a request
, заполненный с помощью OkFunctionHandler[T]
.
Это говорит мне, что перегрузка apply
, которую мы вызываем, следующая:
def apply[T](pair: (Request, AsyncHandler[T])): Future[T]
(OkFunctionHandler
extends AsyncHandler
)
Если вы посмотрите на несколько более похожий на java стиль и с аннотациями типа, у вас есть:
val request: Req = url("http://somesite.com")
val result: Future[String] = Http.apply(request.OK(as.String))
Используя только явные вызовы, он будет больше похож:
val result: Future[String] =
Http.apply(implyRequestHandlerTuple(request).OK(as.String))
Короче говоря, в Http.apply
передается только один параметр, он просто использует стиль без точек для вызова других методов внутри.