【问题标题】:What is the real world example of Scala's Partially applied FunctionScala的部分应用函数的真实例子是什么
【发布时间】:2017-04-04 03:28:09
【问题描述】:

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

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

我想知道这个函数在现实世界中的用途是什么?我尝试阅读不同的博客以查找示例,但找不到有用的示例。

【问题讨论】:

  • 链接:blog.bruchez.name/2011/10/… 提供了一个很好的真实示例,说明如何在 Scala 中使用偏函数。
  • 不是PartialFunction,是部分应用函数!
  • @dk14,它们实际上是两个不同的东西。 PartialFunction 是 Scala 中的一种类型。请参阅我评论中的链接。
  • @jrook 我知道 PartialFunction 是什么。我要说的是,OP 问题中的def partial1 根本不是PartialFunction。该练习的目的是演示一个复杂的部分应用案例——它与任何方式的部分/总功能无关!
  • @jrook OP 只是混淆了两个完全不同但名称相似的东西。

标签: scala function


【解决方案1】:

(在编辑之前与您的问题相关)让我们从术语开始。 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 为所有这些情况提供了一个统一的接口。

【讨论】:

    猜你喜欢
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多