Scala的部分应用函数

时间:2017-04-04 03:28:10

标签: scala function

我是Scala(功能编程)的新手。我正在阅读“Scala中的功能编程”一书。这是一项练习,我们需要定义一个部分应用的函数

def partial1 [A, B, C] (a: A, f: (A, B) => C): B => C = {
    (b: B) => f(a, b)
}

我想知道这个功能的真实用途是什么?我试着阅读不同的博客来找到一个例子,但找不到有用的例子。

1 个答案:

答案 0 :(得分:2)

(在您编辑之前与您的问题相关)让我们从术语开始。 scala中PartialFunctiontrait,表示您的函数可能无法处理输入的所有可能变体:

val partialFunction: PartialFunction[Int, Int] = {
  case 1 => 1
  case 2 => 2
}

scala> partialFunction(1)
res43: Int = 1

scala> partialFunction(3)
scala.MatchError: 3 (of class java.lang.Integer)

这与您的示例完全无关,这是一个partial application - 提供的文章基本上显示了电子邮件过滤的真实示例。

关于部分申请。

有时你可能有一个带有几个参数的函数,比方说:

def sendMail(recipient: String, subject: String, body: String) = println(s"To: $recipient\n Subj: $subject\n Body: $body")

此功能可能是API的一部分,因此您可能无法更改它。现在,假设您需要向许多不同的收件人发送相同的电子邮件:

object Spam{
  val subject = "Hello!"
  val body = "World!"
  def spam(recipient: String) = sendMail(recipient, subject, body)
}

scala> Spam.spam("aaa@aa")
 To: aaa@aa
 Subj: Hello!
 Body: World!

另一种方法是为每个主题/主体生成一个函数,以便使其可自定义:

def spammer(subject: String, body: String): String => Unit = (recipient: String) => {
  sendMail(recipient, subject, body)
}

val spam1 = spammer("Hello", "World!")
spam1("emai@email.com")

它大致相当于OOP:

 class Spammer(subject: String, body: String){
    def apply(recipient: String) = sendMail(recipient, subject, body)
 }

 val spam1 = new Spammer("Hello", "World!")
 spam1("emai@email.com")

不同之处在于,部分应用程序能够更轻松地处理复杂案例,并且还具有额外的语法糖:

 val spam1 = sendMail(_, "Hello", "World!")
 spam1("emai@email.com")

因此,在简单的情况下,您甚至不需要定义自己的包装器。

回到更复杂的例子,你可以这样使用它:

scala> val incrementInt = partial1[Int, Int, Int](1, _ + _)
incrementInt: Int => Int = $$Lambda$1258/21635151@18ca65ea

scala> incrementInt(2)
res47: Int = 3

scala> val incrementList = partial1[List[Int], List[Int], List[Int]](List(0), _ ++ _)
incrementList: List[Int] => List[Int] = $$Lambda$1258/21635151@79f8af90

scala> incrementList(List(0))
res49: List[Int] = List(0, 0)

scala> incrementList(List(0, 0))
res50: List[Int] = List(0, 0, 0)

基本上将某些固定抽象元素(A, B) = C的{​​{1}}添加到未知元素A。在上面的例子中,它添加了整数,并添加了零列表。您可以想象更多实际示例,例如将两个json与一些固定模式合并等等。

您可能会认为B为所有这些案例提供了统一的界面。