scala> val s: Seq[Class[_ <: java.lang.Enum[_]]] = Seq(classOf[java.util.concurrent.TimeUnit])
s: Seq[Class[_ <: java.lang.Enum[_]]] = List(class java.util.concurrent.TimeUnit)
scala> s.flatMap(_.getEnumConstants)
<console>:9: error: no type parameters for method flatMap: (f: Class[_ <: java.lang.Enum[_]] => scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[Seq[Class[_ <: java.lang.Enum[_]]],B,That])That exist so that it can be applied to arguments (Class[_ <: java.lang.Enum[_]] => scala.collection.mutable.ArrayOps[_$1(in value $anonfun) with java.lang.Object] forSome { type _$1(in value $anonfun) <: java.lang.Enum[_] })
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Class[_ <: java.lang.Enum[_]] => scala.collection.mutable.ArrayOps[_$1(in value $anonfun) with java.lang.Object] forSome { type _$1(in value $anonfun) <: java.lang.Enum[_] }
required: Class[_ <: java.lang.Enum[_]] => scala.collection.GenTr... s.flatMap(_.getEnumConstants)
We can use a flatMap() method on a stream with the mapper function List::stream. On executing the stream terminal operation, each element of flatMap() provides a separate stream. In the final phase, the flatMap() method transforms all the streams into a new stream.
The flatMap() method returns a new array formed by applying a given callback function to each element of the array, and then flattening the result by one level.
flatMap() method is method of TraversableLike trait, it takes a predicate, applies it to each element of the collection and returns a new collection of elements returned by the predicate.
Does flatmap() method preserve the order of the streams? Yes, It does and map() also.
Not really the precise answer, but two observations - Scala 2.10 will give you a nicer error:
scala> s.flatMap(_.getEnumConstants)
<console>:9: error: no type parameters for method flatMap: (f: Class[_ <: Enum[_]] => scala.collection.GenTraversableOnce[B])(implicit bf: scala.collection.generic.CanBuildFrom[Seq[Class[_ <: Enum[_]]],B,That])That exist so that it can be applied to arguments (Class[_ <: Enum[_]] => scala.collection.mutable.ArrayOps[(some other)_$1(in object $iw) with Object] forSome { type (some other)_$1(in object $iw) <: Enum[_] })
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Class[_ <: Enum[_]] => scala.collection.mutable.ArrayOps[(some other)_$1(in object $iw) with Object] forSome { type (some other)_$1(in object $iw) <: Enum[_] }
required: Class[_ <: Enum[_]] => scala.collection.GenTraversableOnce[?B]
s.flatMap(_.getEnumConstants)
^
<console>:9: error: type mismatch;
found : Class[_ <: Enum[_]] => scala.collection.mutable.ArrayOps[(some other)_$1(in object $iw) with Object] forSome { type (some other)_$1(in object $iw) <: Enum[_] }
required: Class[_ <: Enum[_]] => scala.collection.GenTraversableOnce[B]
s.flatMap(_.getEnumConstants)
^
<console>:9: error: Cannot construct a collection of type That with elements of type B based on a collection of type Seq[Class[_ <: Enum[_]]].
s.flatMap(_.getEnumConstants)
^
And, if you split your flatMap
, you get to see a simpler version of the issue:
scala> s.map(_.getEnumConstants)
res28: Seq[Array[_$1 with Object] forSome { type _$1 <: Enum[_] }] = List(Array(NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS), Array(RELEASE_0, RELEASE_1, RELEASE_2, RELEASE_3, RELEASE_4, RELEASE_5, RELEASE_6))
scala> res28.flatten
<console>:10: error: No implicit view available from Array[_$1 with Object] forSome { type _$1 <: Enum[_] } => scala.collection.GenTraversableOnce[B].
res28.flatten
^
That is rather surprising since you'd think that it should be easy to turn an Array
into a GenTraversableOnce
. I don't have time to dig out the details at the moment, but I'll point out that the following things seem to work:
s.flatMap(_.getEnumConstants.toSeq)
s.flatMap(_.getEnumConstants.map(_.asInstanceOf[Enum[_]]))
I vote compiler bug, because of this gist, which shows some very weird behaviour in the REPL for this simple script
val s: Seq[Class[_ <: java.lang.Enum[_]]] = Seq(classOf[java.util.concurrent.TimeUnit], classOf[javax.lang.model.SourceVersion])
s.flatMap(_.getEnumConstants.toSeq)
s.flatMap(_.getEnumConstants.toArray)
1234
TimeUnit.getEnumConstants
returns a java array TimeUnit[]
, while flatMap
expects a GenTraversable
You can get by with
scala> s.flatMap(_.getEnumConstants.toSeq)
res4: Seq[Enum[_]] = List(NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With