(在编辑之前与您的问题相关)让我们从术语开始。 PartialFunction 是 Scala 中的 trait,表示您的函数可能无法处理输入的所有可能变化:
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 的(A, B) = C 抽象到未知元素B。在上面的示例中,它是对整数的加法,以及对零列表的加法。您可以想象更实际的示例,例如将两个 json 与某些固定模式合并等等。
您可能会认为partail1 为所有这些情况提供了一个统一的接口。