Pasting Josh’s comment on the linked issue for convenience:
The behaviour of Set#map is quite strange on its own, but especially as an implementation of the Iterable interface, I think the difference in behaviour between Set’s map and that of other Iterables makes it very questionable what is the use-case of Iterable#map at all? If you have an Iterable[T] and you call map on it, you actually do not know if it is deduplicating or not. I cannot think of a situation in which I would like to map each element of an Iterable[T] to something, but then I don’t actually care if the output is deduplicated or not.
def foo(it: Iterable[Int]): Iterable[Int] = it.map(_ / 3)
foo(List(1,2)) // List(0, 0)
foo(Set(1, 2)) // Set(0)
The situation is even more bizarre when you look at Map, which can completely change its behaviour based on if you know it is a Map at compile time:
scala> Map(1 -> 1, 2 -> 1).map(_.swap)
res14: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)
scala> (Map(1 -> 1, 2 -> 1): Iterable[(Int, Int)]).map(_.swap)
res15: Iterable[(Int, Int)] = List((1,1), (1,2))
I think in an ideal world, and maybe something we can shoot for long term, is a situation where Sets and Maps return Iterable s from their map methods, and Seq’s continue as they do today, refining their map output to return Seq :
scala> Map(1 -> 1, 2 -> 1).map(_.swap)
res14: Iterable[(Int, Int)] = List((1,1), (1,2))
scala> (Map(1 -> 1, 2 -> 1): Iterable[(Int, Int)]).map(_.swap)
res15: Iterable[(Int, Int)] = List((1,1), (1,2))
scala> Set(1,2).map(_ / 3)
res18: scala.collection.immutable.Iterable[Int] = List(0, 0)
scala> Seq(1,2).map(_ / 3)
res19: Seq[Int] = List(0, 0)
I think the use case of mapping Set => Set and mapping Map => Map is such a specific/niche transformation/use-case, that it wouldn’t be so inconvenient to just in that case do set.view.map(...).toSet and map.view.map(...).toMap , and leave their implementations Iterable#map to be consistent and predictable with other Iterables.