Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I use `to` in the first argument of Future.traverse, but not `until`?

Why can I use to to construct a Range for the first argument of Future.traverse, but not until? See the following example Scala console interaction.

scala> Future.traverse(1 to 5)(Future.successful)
val res5: scala.concurrent.Future[IndexedSeq[Int]] = Future(<not completed>)

scala> Future.traverse(1 until 5)(Future.successful)
                                 ^
       error: Cannot construct a collection of type scala.collection.immutable.AbstractSeq[Int] with elements of type Int based on a collection of type scala.collection.immutable.AbstractSeq[Int].

scala> res5
val res7: scala.concurrent.Future[IndexedSeq[Int]] = Future(Success(Vector(1, 2, 3, 4, 5)))

scala>

Note that I'm using Scala 2.13.5 for the console though Scala 2.13.2 seems to have the same behavior.

For what it's worth, I noticed that to returns Range.Inclusive, and until returns Range.Exclusive. But both extend Range, so I'm at a loss as to what is different between these two types such that Future.traverse can take one but not the other as the first argument.

like image 579
Tom Wang Avatar asked Jun 02 '21 17:06

Tom Wang


1 Answers

This looks like a combination of several problems.

1 until 5 returns a scala.collection.immutable.Range, while 1 to 5 returns Range.Inclusive.

scala> val exclusive: Range.Exclusive = 1 until 5
                                          ^
       error: type mismatch;
        found   : scala.collection.immutable.Range
        required: Range.Exclusive

scala> val inclusive: Range.Inclusive = 1 to 5
val inclusive: Range.Inclusive = Range 1 to 5

Range.Inclusive is a concrete class, and scala.collection.immutable.Range is the parent of both Range.Inclusive and Range.Exclusive. It looks as though due to the open bug Leo C mentioned, scala.collection.immutable.Range considered only AbstractSeq rather than IndexedSeq (as Silvio Mayolo's comment suggested). And AbstractSeq cannot be constructed. Range.Inclusive, being a concrete class, does not have the same problem.

I am not sure at this point why AbstractSeq cannot be constructed. I had thought the reason was that AbstractSeq is abstract, but IndexedSeq is a trait as well. That said, it is probably by design that AbstractSeq cannot be constructed, but IndexedSeq can.

like image 97
Tom Wang Avatar answered Nov 06 '22 06:11

Tom Wang