Scala 集合:为什么我们需要一个 case 语句来提取高阶函数中的值元组



与映射操作中的元组解包有关,我不明白为什么我们需要一个case(对我来说看起来像一个部分函数(来从元组中提取值,如下所示:

arrayOfTuples map {case (e1, e2) => e1.toString + e2}

而不是以与foldLeft相同的方式提取,例如

def sum(list: List[Int]): Int = list.foldLeft(0)((r,c) => r+c)

无论如何,在第一种情况下我们不指定参数的类型,那么为什么我们需要 case 语句呢?

因为在 Scala 函数中,参数列表和元组不像在 Haskell 和其他函数式语言中那样是一个统一的概念。所以一个函数:

(t: (Int, Int)) => ...

与函数不同:

(e1: Int, e2: Int) => ...

在第一种情况下,您可以使用模式匹配来提取元组元素,这始终使用case语法来完成。实际上,表达式:

{case (e1, e2) => ...}

是以下的简写:

t => t match {case (e1, e2) => ...}

已经有一些关于统一元组和函数参数列表的讨论,但是关于Java重载规则以及默认/命名参数也存在复杂性。所以,我认为这些概念不太可能在Scala中统一起来。

具有一个原始参数的 Lambda

var listOfInt=(1 to 100).toList
listOfInt.foldRight(0)((current,acc)=>current+acc)

您有一个对两个参数进行操作的 lambda 函数。

具有一个元组类型参数的 Lambda

var listOfTuple=List((1,"a"),(2,"b"),(3," "))
listOfTuple.map(x => x._1.toString + x._2.toString)

您有一个 lambda 函数处理一个参数(类型 Tuple2[Int, String] (

两者都适用于类型推断。

具有一个参数的部分 lambda

listOfTuple.map{case (x,y) => x.toString + y.toString}

您有一个 lambda 函数,使用一个参数(类型 Tuple2[Int, String] (。然后,此 lambda 函数在内部使用 Tuple2.unapply 将一个参数分解为多个值。这仍然适用于类型推断。该case是分解("模式匹配"(值所必需的。

此示例有点不直观,因为 unapply 返回一个元组作为其结果。在这种特殊情况下,可能确实有一个技巧,所以 Scala 直接使用提供的元组。但我真的不知道有这样的伎俩。

更新:带有柯里奇的 Lambda 函数

确实有一个技巧。跟

import Function.tupled
listOfTuple map tupled{(x,y) => x.toString + y.toString}

您可以直接使用元组。但当然,这确实是一个技巧:你提供一个对两个参数而不是元组进行操作的函数。 然后,tupled获取该函数并将其更改为其他函数,对元组进行操作。这种技术也称为取消卷曲。

备注:

y已经是字符串时,y.toString是多余的。这不被认为是好的风格。为了举例,我把它留了下来。您应该在实际代码中省略它。

最新更新