有没有一个Scala身份函数?

75

如果我有一个像 List [Option [A]] 这样的东西,并且我希望将其转换为 List [A],标准方法是使用flatMap

scala> val l = List(Some("Hello"), None, Some("World"))
l: List[Option[java.lang.String]] = List(Some(Hello), None, Some(World))

scala> l.flatMap( o => o)
res0: List[java.lang.String] = List(Hello, World)

现在,o => o 只是一个恒等函数。我认为应该有一些方法来执行以下操作:
l.flatMap(Identity) //return a List[String]

然而,我无法让这个工作,因为你无法将object泛型化。我试过一些方法都没有成功;有人能让类似的东西起作用吗?


3
我认为{_}应该等同于{x => x},就像{_ + 3}等同于{x => x+3}一样。有人可以评论一下为什么不是这样吗? - Randall Whitman
4个回答

72

在 Predef 中有一个身份 函数

l flatMap identity[Option[String]]

> List[String] = List(Hello, World)

我认为使用for表达式更好:

for(x <- l; y <- x) yield y
编辑:

我试图弄清楚为什么需要类型参数(Option [String])。问题似乎在于从Option [T]转换为Iterable [T]的类型转换。

如果您将身份函数定义为:

l.flatMap( x => Option.option2Iterable(identity(x)))

类型参数可以省略。


类型推断器为什么不能自己推断出类型?为什么 l.flatMap(identity): List[String] 不能工作? - oxbow_lakes
我认为推理器可以弄清楚这个问题。我不知道。我会加一个问号。 :-) - Thomas Jung
1
@oxbow_lakes - 请查看编辑。这与隐式类型转换有关。 - Thomas Jung
@Thomas - 谢谢。关于identity/Option/Iterable的事情有点遗憾,因为这似乎是最可能使用它的主要场所之一。不幸的是,使用identity比不使用更难读懂。 - oxbow_lakes
这个解决方案似乎在Scala 2.9.1中无法工作。l flatMap identity [Option [String]] <console>:9: 错误:多态表达式不能实例化为预期类型; 找到:Option [String] => Option [String],需要:Option [java.lang.String] => scala.collection.GenTraversableOnce [?] l flatMap identity [Option [String]] ^ - devth

24

顺便说一句,在Scala 2.8中,您只需调用flatten即可。 Thomas 已经在Scala 2.7中基本涵盖了它。他只是错过了一种使用身份标识的替代方法:

l.flatMap[String](identity)

然而,操作符表示法将无法工作(似乎操作符表示法不接受类型参数,这是值得知道的)。

你也可以在Scala 2.7(至少在List上)调用flatten,但是如果没有类型,它将无法执行任何操作。然而,以下内容是可行的:

l.flatten[String]

4
你可以给类型推断器一点帮助:
scala> val l = List(Some("Hello"), None, Some("World"))
l: List[Option[java.lang.String]] = List(Some(Hello), None, Some(World))

scala> l.flatten[String]
res0: List[String] = List(Hello, World)

0

Scala 3:

List(1,2,3).map(identity)

// val res0: List[Int] = List(1, 2, 3)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接