我的问题在下面的代码中表达。
我正在尝试获取一些具有.map函数的输入。我知道,如果我调用.map,它将返回一个Int给我。
// In my case, they are different representations of Ints
// By that I mean that in the end it all boils down to Int
val list: Seq[Int] = Seq(1,2,3,4)
val optInt: Option[Int] = Some(1)
// I can use a .map with a Seq, check!
list.map {
value => println(value)
}
// I can use it with an Option, check!
optInt.map {
value => println(value)
}
// Well, you're asking yourself why do I have to do it,
// Why don't I use foreach to solve my problem. Check!
list.foreach(println)
optInt.foreach(println)
// The problem is that I don't know what I'm going to get as input
// The only thing I know is that it's "mappable" (it has the .map function)
// And that if I were to apply .map it would return Ints to me
// Like this:
def printValues(genericInputThatHasMap: ???) {
genericInputThatHasMap.map {
value => println(value)
}
}
// The point is, what do I have to do to have this functionality?
// I'm researching right now, but I still haven't found anything.
// That's why I'm asking it here =(
// this works:
def printValues(genericInputThatHasMap: Seq[Int]) {
genericInputThatHasMap.map {
value => println(value)
}
}
提前致谢!干杯!
最佳答案
首先快速了解有关map
和foreach
的信息。如果您只想对集合中的每个项目执行带有副作用的操作(例如打印到标准输出或文件等),请使用foreach
。如果您有兴趣通过转换旧元素中的每个元素来创建新集合,请使用map
。实际上,当您编写xs.map(println)
时,您将打印出集合的所有元素,但是您还将获得(完全无用的)单位集合,并且还可能使将来希望使用foreach
的代码的读者(包括您自己)感到困惑。在这样的情况下使用。
现在解决您的问题。在我看来,您已经遇到了Scala标准库中最丑陋的疣之一-名为map
和foreach
(和flatMap
)的方法在语言级别上得到了神奇的对待,而该语言级别与特定类型无关定义它们。例如,我可以这样写:
case class Foo(n: Int) {
def foreach(f: Int => Unit) {
(0 until n) foreach f
}
}
并像这样在
for
循环中使用它,仅仅是因为我已将我的方法命名为foreach
:for (i <- Foo(10)) println(i)
您可以使用structural types在自己的代码中执行类似的操作:
def printValues(xs: { def foreach(f: (Int) => Unit): Unit }) {
xs foreach println
}
在这里,任何具有适当类型的
xs
方法的foreach
(例如Option[Int]
或List[Int]
)都将按预期方式编译和运行。但是,当您尝试使用
map
或flatMap
时,结构化类型会变得更加困惑,并且在其他方面也不令人满意-例如,由于它们使用了运行时反射,它们会带来一些难看的开销。实际上,由于这些原因,它们必须为explicitly enabled in Scala 2.10以避免发出警告。正如senia的答案所指出的,Scalaz library通过使用type classes之类的
Monad
,为问题提供了更加一致的方法。但是,在这种情况下,您不想使用Monad
:它比您需要的功能强大得多。您将使用Each
提供foreach
,并为Functor
提供map
。例如,在Scalaz 7中:import scalaz._, Scalaz._
def printValues[F[_]: Each](xs: F[Int]) = xs foreach println
或者:
def incremented[F[_]: Functor](xs: F[Int]) = xs map (_ + 1)
总而言之,您可以使用结构化类型以标准的,惯用的但丑陋的方式来完成所需的操作,或者可以使用Scalaz获得更干净的解决方案,但要以增加新的依赖关系为代价。
关于scala - 当类在Scala中定义.map函数时,是否可以通过继承(或其他方式)来了解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13893730/