scala:映射元组的未来



我有一个TupleFuture,就像这个Future[(WriteResult, MyObject)] mytuplefuture,我想映射它并用MyObject做一些事情,所以我正在做这个:

mytuplefuture.map((wr,obj)=>{ //do sth});

但我的eclipse scala IDE不允许并建议我这样做:

mytuplefuture.map{ case(wr,obj) => { //do sth }}

这两者有什么区别?

我习惯于做第一个,直到我尝试返回封装在未来中的元组,我才知道第二个

myfuture.map((obj) => { // do sth with obj })

很明显,我正在映射Future的内容,并对其进行处理,这将返回另一个Future,因为原始的myfuture只包含未来的一些东西(obj)。。

有人能解释一下吗?

区别在于:

map是一个以函数为自变量的高阶函数(HOF)。这个函数——为了方便起见,我们称之为映射函数——本身有一个参数,即已完成的Future的值。在这种特殊情况下,这个值恰好是一个元组。您的第一次尝试假设元组可以分为两个参数,然后映射函数会接受这两个参数——但这不会发生,因此出现了错误。

您似乎可以这样定义映射函数(注意参数周围的额外括号):

mytuplefuture.map(((wr,obj)) => /* do sth */)

然而,Scala编译器目前不支持这一点。(也就是说,我认为这可能是未来Scala版本的一个特性。)

因此,另一种选择是使用case语句将映射函数编写为部分函数

mytuplefuture.map {
case (wr,obj) => //
}

实际上是的缩写

mytuplefuture.map {
tuple: (WriteResult, MyObject) => tuple match {
case (wr,obj) => // do sth
}
}

事实上,这种简写通常适用于除打开元组之外的其他情况。例如:

myList.filter {
case A => true
case _ => false
}

是的缩写

myList.filter {
x => x match {
case A => true
case _ => false
}
}

所以,假设您只想查看元组的MyObject成员。您可以将其定义如下:

val myfuture = mytuplefuture.map {
case (_, obj) => obj
}

或者,用元组参数显式表示:

val myfuture = mytuplefuture.map(tuple => tuple._2)

这反过来可以简化为:

val myfuture = mytuplefuture.map(_._2)

其中第一个下划线是映射函数的第一个参数的简写。(第二个下划线,如_2中所示,是元组中第二个值的名称的一部分,而不是简写——这就是Scala可能会让人有点困惑的地方。)

前面三个示例都返回一个Future[MyObject]

如果随后将map应用于该值,则在这种情况下,单个映射函数参数将是MyObject实例。因此,您现在可以写:

myfuture.map(obj => /* Do something with obj */)

至于问题的其余部分,应用于Future值的映射函数确实适用于原始future的结果,因为在第一个future完成之前无法执行它。因此,map返回一个未来,当第一个未来完成时(成功或不成功)。

更新:澄清了map的论点。感谢@AlexeyRomanov纠正了我的错误,也感谢@RhysBradbury指出了我最初的错误。;-)

不同之处在于,case表示对象的分解(或提取)(调用unapply,您可以自己实现)。

在本例中,myfuture.map(obj => obj._2 )obj-是您的元组,因此您可以通过._1._2访问其元素

CCD_ 21将元组分解为其元素。

通过在带有默认unapply实现的case class上使用这种方法,您可以更好地感受到差异

case class MyClass(int: Int)
List(MyClass(1)) map { myclass => myclass.int } // accesing the elements
List(MyClass(1)) map { case MyClass(i) => i + 1 } // decomposition 

在你的情况下,我会写

mytuplefuture.map(_.2).map( // do somthing )

p.S。您可以为许多其他类(例如Option)执行提取操作。它还允许你写一些类似的东西

val (a, b) = tuple
val MyClass(x) = myclass

最新更新