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

eug*_*ied 11 scala

Map Operations中的Tuple Unpacking相关,我不明白为什么我们需要一个case(看起来像我的部分函数)从元组中提取值,如下所示:

arrayOfTuples map {case (e1, e2) => e1.toString + e2}
Run Code Online (Sandbox Code Playgroud)

相反,以同样的方式提取它的工作原理在foldLeft,例如

def sum(list: List[Int]): Int = list.foldLeft(0)((r,c) => r+c)
Run Code Online (Sandbox Code Playgroud)

无论如何我们没有在第一种情况下指定参数的类型,那么为什么我们需要这个case声明呢?

Jes*_*erg 12

因为在Scala函数中,参数列表和元组不是统一的概念,因为它们在Haskell和其他函数式语言中.所以一个功能:

(t: (Int, Int)) => ...
Run Code Online (Sandbox Code Playgroud)

与功能不同:

(e1: Int, e2: Int) => ...
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,您可以使用模式匹配来提取元组元素,并且总是使用case语法来完成.实际上,表达式:

{case (e1, e2) => ...}
Run Code Online (Sandbox Code Playgroud)

是简写:

t => t match {case (e1, e2) => ...}
Run Code Online (Sandbox Code Playgroud)

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


ste*_*hke 5

带有一个原始参数的 Lambda

var listOfInt=(1 to 100).toList
listOfInt.foldRight(0)((current,acc)=>current+acc)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

两者都适用于类型推断。

带一个参数的部分 lambda

listOfTuple.map{case (x,y) => x.toString + y.toString}
Run Code Online (Sandbox Code Playgroud)

您有一个 lambda 函数,使用一个参数(类型为Tuple2[Int, String])。然后在Tuple2.unapply内部使用此 lambda 函数将一个参数分解为多个值。这仍然适用于类型推断。的case是需要的值的分解(“图案匹配”)。

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

更新:带柯里化的 Lambda 函数

确实有窍门。和

import Function.tupled
listOfTuple map tupled{(x,y) => x.toString + y.toString}
Run Code Online (Sandbox Code Playgroud)

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

评论:

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