Just now I am surprised to learn that mapValues
produces a view. The consequence is shown in the following example:
case class thing(id: Int)
val rand = new java.util.Random
val distribution = Map(thing(0) -> 0.5, thing(1) -> 0.5)
val perturbed = distribution mapValues { _ + 0.1 * rand.nextGaussian }
val sumProbs = perturbed.map{_._2}.sum
val newDistribution = perturbed mapValues { _ / sumProbs }
The idea is that I have a distribution, which is perturbed with some randomness then I renormalize it. The code actually fails in its original intention: since mapValues
produces a view
, _ + 0.1 * rand.nextGaussian
is always re-evaluated whenever perturbed
is used.
I am now doing something like distribution map { case (s, p) => (s, p + 0.1 * rand.nextGaussian) }
, but that's just a little bit verbose. So the purpose of this question is:
- Remind people who are unaware of this fact.
- Look for reasons why they make
mapValues
output view
s.
- Whether there is an alternative method that produces concrete
Map
.
- Are there any other commonly-used collection methods that have this trap.
Thanks.
Question&Answers:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…