我有Future
Tuple
这样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 })
很明显,我正在绘制未来的内容,并用它做一些事情,这会带来另一个未来,因为原来的myfuture在未来只包含一些东西(obj)。
有人会解释吗?
答案 0 :(得分:3)
区别在于:
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 可能会让人感到困惑的地方。)< / p>
前三个示例中的所有示例都返回Future[MyObject]
。
如果您随后将map
应用于此值,则此案例中的单个映射函数参数将是您的MyObject
实例。因此,你现在可以写:
myfuture.map(obj => /* Do something with obj */)
至于问题的其余部分,应用于Future
值的映射函数确实适用于原始未来的结果,因为它可以& #39;执行直到第一个未来完成。因此,map
返回在第一个未来完成时(成功或以其他方式)完成的未来。
更新:明确了map
的参数究竟是什么。感谢@AlexeyRomanov让我说得对,感谢@RhysBradbury指出我的初始错误。 ; - )
答案 1 :(得分:-1)
不同之处在于,case
表示对象的分解(或提取)(调用unapply
,您可以自己实现)。
myfuture.map(obj => obj._2 )
obj - 是您的元组,因此您可以通过._1
和._2
mytuplefuture.map{ case(wr,obj) => { //do sth }}
这会将元组分解为元素。
您可以通过case class
使用此方法来更好地感受到差异,该方法带有默认的unapply
实施
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