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 передается только один параметр, он просто использует стиль без точек для вызова других методов внутри.