Scala';s部分应用函数

Scala';s部分应用函数,scala,function,Scala,Function,我是Scala(函数式编程)的新手。我正在读《Scala中的函数编程》一书。这是一个练习,我们需要定义一个部分应用的函数 def partial1 [A, B, C] (a: A, f: (A, B) => C): B => C = { (b: B) => f(a, b) } 我想知道这个函数的实际用途是什么?我试着阅读不同的博客来寻找一个例子,但找不到一个有用的例子。(与您编辑之前的问题相关)让我们从术语开始PartialFunction在scala中表示,您的函数

我是Scala(函数式编程)的新手。我正在读《Scala中的函数编程》一书。这是一个练习,我们需要定义一个部分应用的函数

def partial1 [A, B, C] (a: A, f: (A, B) => C): B => C = {
    (b: B) => f(a, b)
}
我想知道这个函数的实际用途是什么?我试着阅读不同的博客来寻找一个例子,但找不到一个有用的例子。

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

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)
这与您的示例完全无关,这是一个-本文基本上展示了带有电子邮件过滤的真实示例


关于部分应用

有时,您可能有一个具有多个参数的函数,比如:

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
的加法
(A,B)=C
进行抽象。在上面的例子中,它是对整数的加法,以及对零列表的加法。您可以想象更实际的例子,比如用固定模式合并两个json等等

您可能会认为
partail1
为所有这些情况提供了统一的接口。

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

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)
这与您的示例完全无关,这是一个-本文基本上展示了带有电子邮件过滤的真实示例


关于部分应用

有时,您可能有一个具有多个参数的函数,比如:

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
的加法
(A,B)=C
进行抽象。在上面的例子中,它是对整数的加法,以及对零列表的加法。您可以想象更实际的例子,比如用固定模式合并两个json等等


您可能会认为,
partail1
为所有这些情况提供了一个统一的接口。

链接:提供了一个在Scala中如何使用分部函数的真实示例。它不是分部函数,而是部分应用的函数@dk14,它们实际上是两个不同的东西。PartialFunction是Scala中的一种类型。请参阅我评论中的链接。@jrook我知道PartialFunction是什么。我想说的是OP问题中的
def partial1
根本不是
PartialFunction
。该练习的重点是演示一个复杂的部分应用程序案例——它与部分/全部函数没有任何关系@jrook OP只是混淆了两个名称相似的完全不同的东西。链接:给出了一个在Scala中如何使用分部函数的真实示例。它不是分部函数,而是部分应用函数@dk14,它们实际上是两个不同的东西。PartialFunction是Scala中的一种类型。请参阅我评论中的链接。@jrook我知道PartialFunction是什么。我想说的是OP问题中的
def partial1
根本不是
PartialFunction
。该练习的重点是演示一个复杂的部分应用程序案例——它与部分/全部函数没有任何关系@jrook OP只是用相似的名称混淆了两个完全不同的东西。