1

我试图了解函数部分应用程序在 Scala 中的工作原理。

为此,我构建了这个简单的代码:

object Test extends App {
  myCustomConcat("General", "Public", "License") foreach print

  GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print

  def myCustomConcat(strings: String*): List[Char] = {
    val result = for (s <- strings) yield {
      s.charAt(0)
    }

    result.toList
  }


  def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ) = {

    myCustomConcat("General", "Public", "License")
  }
}

myCostumConcat函数输入一个字符串数组,它返回一个包含每个字符串第一个字母的列表。

所以,代码

myCustomConcat("General", "Public", "License") foreach print

将在控制台上打印:GPL

现在假设我想编写一个函数来生成 GPL 首字母缩写词,使用(作为输入参数)我之前的函数提取每个字符串的第一个字母:

def GeneralPublicLicenceAcronym (concatFunction: (String*) => List[Char] ): List[Char] = {

    myCustomConcat("General", "Public", "License")
  }

使用部分应用程序运行这个新功能:

GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print

我收到此错误:

错误:(8, 46) 类型不匹配;发现:Seq[String] required: String GeneralPublicLicenceAcronym(myCustomConcat(_)) foreach print

为什么?在这种情况下我可以使用部分应用程序吗?

4

1 回答 1

4

您需要做的就是更改myCustomConcat(_)myCustomConcat _,或者实际上只是myCustomConcat

您所做的并不完全是部分应用程序-它只是将方法用作函数值。

在某些情况下(需要函数值)编译器会理解您的意思,但在其他情况下,您通常需要使用_后缀告诉编译器您的意图。

“部分应用”意味着我们为函数提供一些但不是全部的参数,以创建一个新函数,例如:

  def add(x: Int, y: Int) = x + y           //> add: (x: Int, y: Int)Int

  val addOne: Int => Int = add(1, _)        //> addOne  : Int => Int = <function1>

  addOne(2)                                 //> res0: Int = 3

我想您的情况可以被视为部分应用程序,但不应用任何参数-您可以_*在此处使用部分应用程序语法,但是由于重复的参数 ( ),您需要给编译器一个提示String*,这最终有点难看:

myCustomConcat(_:_*)

另请参阅:Scala type ascription for varargs using _* cause error

于 2015-06-18T17:56:51.957 回答