【问题标题】:Scala dispatch exampleScala 调度示例
【发布时间】:2015-01-26 02:12:24
【问题描述】:

我是一名 Java 工程师,最近在慢慢学习 Scala。我遇到了一些使用 Dispatch 发出简单 GET 请求的示例代码:

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

问题是……我不太明白这里发生了什么。首先,Http是一个类吗?还是一种方法?其次,传递给它的参数是怎么回事?我想也许我们传递了三个参数,Scala 允许我们省略逗号。但是当我尝试添加逗号时,我得到了一个编译错误,所以这是不对的。

我确信这对于精通 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 方法的单例对象,该方法返回Req 案例类的实例。 Http 也是一个单例对象,它还有一个apply 方法。 Httpapply 采用两个参数列表——第一个采用单个 Req 参数,第二个采用执行上下文(您可以将其视为 Java 的 Executor 的 Scala 版本)。

implyRequestHandlerTuple 是一个隐式 方法。 Req 没有 OK 方法,但编译器知道 RequestHandlerTupleBuilder 类有(并且它接受适当的参数——在本例中是从 Response 到某种类型的函数),所以在原始版本它自动应用此方法从Req进行转换。

最后,as 是一个包含 String 单例对象的包。这个对象扩展了Response => String(这是Function1[Response, String]的更多语法糖。我们的OK方法正在寻找一个采用Response的函数,所以我们很好。

最后你得到了Future[String]。有很多关于期货的other places 可以阅读,所以我不会在这里详细介绍,但简而言之,这个值可能不满足(即您仍在等待结果),或者对失败感到满意(在网络错误等情况下),或成功满足(在这种情况下它将包含响应正文)。

【讨论】:

  • 也许您提前 12 秒开始,或者您知道要省略哪些单词。您在工作中的人文教育资金。在她开始下一份读书报告之前,我将让我的女儿阅读这个答案。我看到你使用了罗伯茨女士推荐的过渡词:“终于”、“最终”。检查加!
【解决方案2】:

url (本质上)是一个返回Req 对象的方法。所以request 的类型为Req

Http 是一个带有伴生对象的类,该对象有几个apply 方法的重载。所以当你看到:

Http(request OK as.String)

它实际上是语法糖:

Http.apply(request OK as.String)

好的,那么apply 内部发生了什么?似乎在 request 上调用了一个名为 OK 的方法。但是查看API Docs,您可能会注意到Req 类型没有这种方法OK。然而,有一个名为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 将返回一个RequestOkFunctionHandler[T] 的元组。

这告诉我我们调用的apply 的重载是这个:

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

(OkFunctionHandler 扩展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,它只是使用无点样式调用其中的其他方法。

【讨论】:

  • 哇,我想我比你快了 12 秒。我也喜欢你的回答,但你可以更清楚地知道request OK as.String 被解析为request.OK(as.String)
  • @TravisBrown 很难比底部的解释更清楚。但是url 本质上是一种方法吗?如果 ScalaDoc 有一个“用例”,您可以在其中单击方法 url 并将您带到带有应用的对象,那就没问题了。我希望 ScalaDoc 的人没有阅读这篇文章。
  • 我对@9​​87654364@ 视而不见,因为 OP 并没有真正询问它。现在我有一个非官方的衡量标准,即制作一个@TravisBrown 需要多少人。
  • 有一个 +1 以缩小差距。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多