理解scala中的函数

时间:2016-11-06 20:54:31

标签: scala function

问题严格来说是Scala语法,虽然它包含了akka的一些代码(作为示例)。

我对Scala很新。深入研究akka的源代码我想出了以下非常奇怪的方法:

def transform[C]
 (f: ExecutionContext ⇒ Materializer ⇒ Future[B] ⇒ Future[C]): Unmarshaller[A, C] =
Unmarshaller.withMaterializer { implicit ec ⇒ implicit mat ⇒ a ⇒ f(ec)(mat)(this(a)) }

其中Unmarshaller.withMaterializer定义为

  def withMaterializer[A, B](f: ExecutionContext ⇒ Materializer => A ⇒ Future[B]): Unmarshaller[A, B]

这里发生了什么?什么是可怕的函数f: ExecutionContext => Materializer => Future[B] => Future[C]。对我来说似乎更奇怪的是implicit s:implicit ec => implicit mat => a => f(ec)(mat)(this(a))的序列,尽管withMaterializer根本没有隐含参数。

这些序列中的隐含意味着什么?

2 个答案:

答案 0 :(得分:2)

f: ExecutionContext => Materializer => Future[B] => Future[C]只不过是一个curried函数,因此您可以将其称为f(ec)(mat)(this(a)),其中包含多个参数列表(从技术上讲,参数列表不属于{{1但是那些都是细节)。换句话说,def f(...)(...)可以写成:

f

(返回函数的函数,返回另一个函数)

现在,如果您查看f: ExecutionContext => { Materializer => { Future[B] => Future[C] } }` ,则会在f(ec)(mat)(this(a))上方定义一个电话this(a)

transform

def apply(value: A)(implicit ec: ExecutionContext, materializer: Materializer): Future[B] 只是对this(a)的调用。现在this.apply(a)有两个隐式参数,即applyec: ExecutionContext,因此要像materializer:Materializer一样调用它,您需要两个隐式值。这正是this(a)定义的含义。它声明implicit ec ⇒ implicit mat ⇒ a ⇒ f(ec)(mat)(this(a))ec作为所有嵌套函数体的含义,因此mat可以选择它们。另一种可能性是写:

this(a)

答案 1 :(得分:0)

它是一个带有currying和隐含参数的lambda(应该在声明的范围内)。

"可怕"函数类型语法是currying:一个参数的函数,它接受ExecutionContext并返回一个参数的另一个函数,它接受Materializer并返回另一个函数,......等等。另一件事是{ {3}}。

这是一个类似结构的简单例子:

implicit val implicitInt: Int = 5
implicit val implicitString: String = "0"

val f: Int => String => String = {
  implicit a => {
    implicit b => {
      a.toString + b
    }
  }
}

此处f是一个curried函数,它接受Int并返回一个带String并返回String的函数。函数值声明的一般语法是val f = { argument => ... },因此如果您将此参数设为隐式,则意味着范围中必须存在此类型的实例,该实例将用作默认值。您仍然可以将f应用于某些参数:f(1)(""),因为它仍然是一个函数。

您可以通过为每个步骤定义嵌套函数来重写您更详细询问的代码:

def transform[C](f: ExecutionContext ⇒ Materializer ⇒ Future[B] ⇒ Future[C]): Unmarshaller[A, C] = {

  def getExecutionContext(implicit ec: ExecutionContext): Materializer => (A => Future[B]) = {

    def getMaterializer(implicit mat: Materializer): A => Future[B] = {

      def applyF(a: A): Future[B] = f(ec)(mat)(this(a))
      applyF // : A => Future[B]
    }

    getMaterializer // : Materializer => (A => Future[B])
  }

  Unmarshaller.withMaterializer(
    getExecutionContext // : ExecutionContext => (Materializer => (A => Future[B]))
  )
}