I find myself doing `buildSet { foo.mapTo(this) { ...
# stdlib
d
I find myself doing
buildSet { foo.mapTo(this) { ... } }
instead of
foo.map { ... }.toSet()
to avoid iterating twice... could the stdlib maybe provide
mapToSet { ... }
?
j
This seems to have been reported before, but it doesn't have many upvotes: https://youtrack.jetbrains.com/issue/KT-51435/Request-offer-alternative-to-map-which-returns-a-Set-HashSet
👍 1
j
Presumably you don't want to do
mapTo(HashSet()) { .. }
because it returns the mutable type?
d
Exactly...
That's why I use buildSet...
I guess if someone would want a mutable type, then it's not much longer to write
mapTo(HashSet()) { .. }
, that's probably why that issue didn't really get upvoted...
j
I usually just ignore the fact that the local is mutable because usually it quickly flows into something else or returns where it's exposed as a read-only set
4
At some point though there's a pragmatism argument where it comes up soooo muuuuuch that it probably should be provided
👌🏼 1
d
because usually it quickly flows into something else or returns where it's exposed as a read-only set
Yeah, we could make do in some cases like you said, but I'd always rather not rely on that, since with a little unconscious refactoring one could end up making mistakes, especially with IDE refactoring features and AI...
And it seems to happen pretty often...
j
I do wish there was a
mapToSet
, especially when mapping elements from a
Set
. It just feels more natural when I do need to return a set. Admittedly this doesn't come up very often, but every time it does, it feels awkward.
j
i'm not sure the source collection being a Set makes that much of a difference. The likelihood of the result of your resulting collection having set semantics shouldn't really be tied to the semantics of the originating collection.
A smarter compiler could make
.map { .. }.toSet()
do the right thing, but smarter compilers are slower.
d
Admittedly this doesn't come up very often,
I came across quite a few recently when I needed to subtract keys from a map and the IDE tells you sets are more efficient... but there are a bunch of other places too... and using buildSet is pretty ugly there...
j
I suppress that warning a lot
🤔 1
Nothing about a set makes that operation more efficient under the hood. It's the semantics of a set that do, and you can have those in any collection.
j
> i'm not sure the source collection being a Set makes that much of a difference. The likelihood of the result of your resulting collection having set semantics shouldn't really be tied to the semantics of the originating collection. @jw You're theoretically right. The mapping function doesn't necessarily preserve the uniqueness property of the set. In practice, it often does, though. I would add to that that the order of the resulting list is arbitrary when the source is an (unordered) set.
d
In that map subtraction, I need to use
map { }
to get the key anyways... so might as well do it to a set? But interesting... so that IDE comment is wrong?
j
It's not wrong, per se. But often I will have more knowledge about the incoming collection already having the desired semantics. In general calling toSet() ensures minimal operations on the map. It doesn't want a 1000-element list resulting in only 10 map ops.
a
Converting
foo
to a sequence seems like it would solve the double-iteration problem, but I guess that could be considered too much overhead
r
FWIW, I often run into a similar issue with
.map { }.toImmutableList()
(or
toImmutableSet()
), which has a lot of overlap with this problem
👍 2
t
Perhaps we could introduce new variants to the existing functions, that takes in an extra transformation function. If I recall correctly, none of the existing type-transforming functions (e.g.
toList, toMutableList, toSet, toMutableSet, toHashSet, toMap, toMap, toCollection
) has
transform: (T) -> R
as argument, we could simply introduce that. I think
foo.toSet{ ... }
is quite readable