1

Strange as it may seem, this does not work:

scala> (1 to 6).toSet map (_ / 2)
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.$div(2))
              (1 to 6).toSet map (_ / 2)
                                  ^

However, using to[Set] instead of toSet does:

scala> (1 to 6).to[Set] map (_ / 2)
res0: scala.collection.immutable.Set[Int] = Set(2, 0, 3, 1)

Huh. o_O

Also consider that this works:

scala> val s = (1 to 6).toSet; s map (_ / 2)
s: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)
res1: scala.collection.immutable.Set[Int] = Set(2, 0, 3, 1)

As Range.Inclusive is a first-order type, as suggested by @AlexIv, keep in mind that this also won't work with List[Int]:

scala> List(1, 2, 3, 4, 5, 6).toSet map (_ / 2)
<console>:8: error: missing parameter type for expanded function ((x$1) => x$1.$
div(2))
              List(1, 2, 3, 4, 5, 6).toSet map (_ / 2)
                                                ^

And as previously, this works:

scala> val s = List[Int](1, 2, 3, 4, 5, 6).toSet; s map (_ / 2)
s: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)
res3: scala.collection.immutable.Set[Int] = Set(2, 0, 3, 1)

Edit: duplicate of Type inference fails on Set made with .toSet?

Community
  • 1
  • 1
Michal Rus
  • 1,796
  • 2
  • 18
  • 27

1 Answers1

1

The typer phase (scala -Xprint:typer) hides the answer:

private[this] val res7: <error> = Predef.intWrapper(1).to(6).toSet[B].map[B, That]({
  ((x: Nothing) => Predef.identity[Nothing](x))
})();

(1 to 6) returns a Range.Inclusive, which is a first-order type and not a type constructor, it's not parameterized, but Set[A] expects/requires you to provide it some type and returns you a type. When you call toSet, scalac expects some type, cause Inclusive doesn't have toSet method, it's inherited from TraversableOnce and is a generic method, so you need explicitly provide some type:

(1 to 6).toSet[Int].map(identity)
res0: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

toBuffer also doesn't work, other conversions works perfectly and this two methods have a similar implementation:

def toBuffer[B >: A]: mutable.Buffer[B] = to[ArrayBuffer].asInstanceOf[mutable.Buffer[B]]

def toSet[B >: A]: immutable.Set[B] = to[immutable.Set].asInstanceOf[immutable.Set[B]]
4lex1v
  • 21,367
  • 6
  • 52
  • 86
  • Okay. But this also won't work with a `List[Int]` which is a type constructor. (Updating the question.) – Michal Rus Oct 20 '13 at 22:30
  • @MichałRus i've added some info. Methods `toSet` and `toBuffer` expects a type argument which has `A` as it's lower bound. So it is inferred as `toSet[B >: Int]`. – 4lex1v Oct 20 '13 at 22:49