在尝试使用scala中的Options时,我遇到了这个特殊的问题。
我开始创建List [Option [Int]],如下所示:
scala> List(Some(1),Some(2),None,Some(3))
res0: List[Option[Int]] = List(Some(1), Some(2), None, Some(3))
然后我尝试在res0中列表的条目上映射一个加法,如下所示:
scala> res0 map (_ + 1)
这给了我错误:
<console>:9: error: type mismatch;
found : Int(1)
required: String
res0 map (_ + 1)
^
然后我尝试在条目上添加flatMapping,如下所示:
scala> res0 flatMap (_ + 1)
这给了我同样的错误:
<console>:9: error: type mismatch;
found : Int(1)
required: String
res0 flatMap (_ + 1)
^
但像res0.flatMap(r => r)
这样的东西可以很好地结果:
res9: List[Int] = List(1, 2, 3)
有人可以告诉我为什么将地址添加到1会对地图和flatMap都失败吗?
答案 0 :(得分:6)
您尝试的前两件事失败了,因为您尝试将Option
添加到Int
,而这是不可能的。
出现奇怪的错误消息是因为Scala假定,因为Option
没有+
方法,您正在尝试String
连接,但是您必须添加一个Option
到String
,或String
到Option
,而您没有,因此出现错误消息。
在最后一种情况下,您没有尝试添加任何内容,只是按原样返回Option
,因此没有错误消息。
答案 1 :(得分:1)
尝试使用get从Some[Int]
提取值到Int
,允许进行计算value + 1
,即:
res0 map{_.getOrElse(0) + 1}
正如@ Sepp2k所指出的那样,您也可以使用collect
来避免None
的默认值
res0 collect {case Some(x) => x + 1 }
答案 2 :(得分:1)
要递增所有不是None
的值,您还需要映射列表中的每个Option
元素,如下所示:
scala> res0.map(_.map(_ + 1))
res1: List[Option[Int]] = List(Some(2), Some(3), None, Some(4))
如果你想过滤掉None
,你确实会使用flatMap
:
scala> res0.flatMap(_.map(_ + 1))
res2: List[Int] = List(2, 3, 4)
答案 3 :(得分:1)
赋予flatMap
的函数以及赋给map
的函数都采用列表元素类型的值 - 在本例中为Option[Int]
。但是,您的函数_ + 1
需要Int
,而不是Option[Int]
,因此在这种情况下,您无法将其用作map
或flatMap
的参数。此外,赋予flatMap
的函数应该返回一个可迭代的¹,但是你的函数会返回一个数字。
这将做你想做的事:res0 flatMap (_ map (_ + 1))
。这里给flatMap
的函数需要Option[Int]
,并通过调用该选项上的Option[Int]
返回map
。 flatMap
然后获取函数返回的选项并连接它们。
¹技术上是GenTraversableOnce
。
答案 4 :(得分:1)
您尝试在e.+(1)
中的每个元素e
上调用List[Option[Int]]
,但+
不是Option[_]
声明的函数。但是,字符串连接是可能的(我假设存在从Any
到String
的隐式),但是只有当第二个参数也是一个字符串时(不确定为什么隐含了我的假设)这里不考虑。)
您可以通过使用@korefn建议的默认值来解决此问题,或者在Some(x)
的另一个调用中“隐藏”None
和map
之间的区别,即由
map(_.map(_ + 1))
答案 5 :(得分:1)
它们失败了,因为类型错误,编译器正确地说明了它。
地图案例失败,因为map
需要一个函数A => B
。在您的代码中,A => B
确实是Int => Int
,因为在您的列表中调用map
意味着A
实际上是Option[Int]
。
此外,flatMap
需要A => F[B]
形式的函数。如果你做res0 flatMap { o => o map { a => a + 1 } }
,你会得到答案。这基本上是扩展:
for {
element <- res0 // o above
value <- element // a above
} yield value + 1