我是Scala(功能编程)的新手。我正在阅读“Scala中的功能编程”一书。这是一项练习,我们需要定义一个部分应用的函数
def partial1 [A, B, C] (a: A, f: (A, B) => C): B => C = {
(b: B) => f(a, b)
}
我想知道这个功能的真实用途是什么?我试着阅读不同的博客来找到一个例子,但找不到有用的例子。
答案 0 :(得分:2)
(在您编辑之前与您的问题相关)让我们从术语开始。 scala中PartialFunction
为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, B) = C
的{{1}}添加到未知元素A
。在上面的例子中,它添加了整数,并添加了零列表。您可以想象更多实际示例,例如将两个json与一些固定模式合并等等。
您可能会认为B
为所有这些案例提供了统一的界面。