This page is no longer maintained — Please continue to the home page at www.scala-lang.org

SortedMap.mapValues

4 replies
phlegmaticprogrammer
Joined: 2010-07-23,
User offline. Last seen 2 years 15 weeks ago.

Hi,

is there a fundamental flaw in how the data structure library of Scala works, or did I just not figure out the right way to do it? Or is it maybe a flaw that is not so fundamental, but easily fixed?

In the following code:

def mutate(v : Value) : Value = ...

messages.mapValues(mutate).asInstanceOf[SortedMap[Program.Message, Value]]

a classCastException is thrown, it's not a SortedMap, but something "MapLike" ...
The nice thing about SortedMap.mapValues is that it should work in linear time and return a SortedMap, but obviously it doesn't. How do I do the above properly ?

Cheers,

Steven

roland.kuhn
Joined: 2011-02-21,
User offline. Last seen 35 weeks 3 days ago.
Re: SortedMap.mapValues

On Jun 20, 2011, at 17:17 , Steven Obua wrote:

> Hi,
>
> is there a fundamental flaw in how the data structure library of Scala works, or did I just not figure out the right way to do it? Or is it maybe a flaw that is not so fundamental, but easily fixed?
>
> In the following code:
>
> def mutate(v : Value) : Value = ...
>
> messages.mapValues(mutate).asInstanceOf[SortedMap[Program.Message, Value]]
>
> a classCastException is thrown, it's not a SortedMap, but something "MapLike" ...
> The nice thing about SortedMap.mapValues is that it should work in linear time and return a SortedMap, but obviously it doesn't. How do I do the above properly ?
>
First of all: do not use .asInstanceOf[], ever ;-)

Seriously, .asInstanceOf[] just overrides the static type, but what you want—at least as far as I can infer from your mail—is a conversion. The straight-forward would be

scala> Map(1->2)
res0: scala.collection.immutable.Map[Int,Int] = Map(1 -> 2)

scala> collection.SortedMap(res0.mapValues(_ + 1).toSeq:_*)
res10: scala.collection.SortedMap[Int,Int] = Map(1 -> 3)

and a (probably) more efficient way for huge maps might be

scala> collection.SortedMap.empty[Int,Int] ++ res0.toStream.map{case (k,v) => (k,v+1)}
res5: scala.collection.immutable.SortedMap[Int,Int] = Map(1 -> 3)

Regards,

Roland

roland.kuhn
Joined: 2011-02-21,
User offline. Last seen 35 weeks 3 days ago.
Re: SortedMap.mapValues

On Jun 20, 2011, at 17:17 , Steven Obua wrote:

> is there a fundamental flaw in how the data structure library of Scala works, or did I just not figure out the right way to do it? Or is it maybe a flaw that is not so fundamental, but easily fixed?
>
> In the following code:
>
> def mutate(v : Value) : Value = ...
>
> messages.mapValues(mutate).asInstanceOf[SortedMap[Program.Message, Value]]
>
> a classCastException is thrown, it's not a SortedMap, but something "MapLike" ...
> The nice thing about SortedMap.mapValues is that it should work in linear time and return a SortedMap, but obviously it doesn't. How do I do the above properly ?
>
Oops, sorry: I misunderstood the issue. “messages” is already a SortedMap, right? SortedMap exists only in collection.immutable and it seems that mapValues does not benefit from the advanced CanBuildFrom pattern which fixes this issue for “map”:

scala> res10 map { case (k, v) => (k, v*2) }
res13: scala.collection.SortedMap[Int,Int] = Map(1 -> 6)

So, the work-around would be to use “map” instead of “mapValues”.

Regards,

Roland

phlegmaticprogrammer
Joined: 2010-07-23,
User offline. Last seen 2 years 15 weeks ago.
Re: SortedMap.mapValues

Ok, thanks, it works when using "map" instead of "mapValues". It's not optimal because of the worse complexity (O(n log n) instead of just O(n)), but it'll do. Is this just some accidental flaw, or is there a deeper reason why this works for map, but not for mapValues ?

Cheers,

Steven

On 20.06.2011, at 17:47, Roland Kuhn wrote:

>
> On Jun 20, 2011, at 17:17 , Steven Obua wrote:
>
>> is there a fundamental flaw in how the data structure library of Scala works, or did I just not figure out the right way to do it? Or is it maybe a flaw that is not so fundamental, but easily fixed?
>>
>> In the following code:
>>
>> def mutate(v : Value) : Value = ...
>>
>> messages.mapValues(mutate).asInstanceOf[SortedMap[Program.Message, Value]]
>>
>> a classCastException is thrown, it's not a SortedMap, but something "MapLike" ...
>> The nice thing about SortedMap.mapValues is that it should work in linear time and return a SortedMap, but obviously it doesn't. How do I do the above properly ?
>>
> Oops, sorry: I misunderstood the issue. “messages” is already a SortedMap, right? SortedMap exists only in collection.immutable and it seems that mapValues does not benefit from the advanced CanBuildFrom pattern which fixes this issue for “map”:
>
> scala> res10 map { case (k, v) => (k, v*2) }
> res13: scala.collection.SortedMap[Int,Int] = Map(1 -> 6)
>
> So, the work-around would be to use “map” instead of “mapValues”.
>
> Regards,
>
> Roland

roland.kuhn
Joined: 2011-02-21,
User offline. Last seen 35 weeks 3 days ago.
Re: SortedMap.mapValues

Given that an “innocent” method like mapValues changes the characteristics to “unsorted”, I’d think this is a bug. Care to file a ticket? It seems that other methods of SortedMap were fixed recently (e.g. ticket 4112).

Regards,

Roland

On Jun 20, 2011, at 18:02 , Steven Obua wrote:

> Ok, thanks, it works when using "map" instead of "mapValues". It's not optimal because of the worse complexity (O(n log n) instead of just O(n)), but it'll do. Is this just some accidental flaw, or is there a deeper reason why this works for map, but not for mapValues ?
>
> Cheers,
>
> Steven
>
> On 20.06.2011, at 17:47, Roland Kuhn wrote:
>
>>
>> On Jun 20, 2011, at 17:17 , Steven Obua wrote:
>>
>>> is there a fundamental flaw in how the data structure library of Scala works, or did I just not figure out the right way to do it? Or is it maybe a flaw that is not so fundamental, but easily fixed?
>>>
>>> In the following code:
>>>
>>> def mutate(v : Value) : Value = ...
>>>
>>> messages.mapValues(mutate).asInstanceOf[SortedMap[Program.Message, Value]]
>>>
>>> a classCastException is thrown, it's not a SortedMap, but something "MapLike" ...
>>> The nice thing about SortedMap.mapValues is that it should work in linear time and return a SortedMap, but obviously it doesn't. How do I do the above properly ?
>>>
>> Oops, sorry: I misunderstood the issue. “messages” is already a SortedMap, right? SortedMap exists only in collection.immutable and it seems that mapValues does not benefit from the advanced CanBuildFrom pattern which fixes this issue for “map”:
>>
>> scala> res10 map { case (k, v) => (k, v*2) }
>> res13: scala.collection.SortedMap[Int,Int] = Map(1 -> 6)
>>
>> So, the work-around would be to use “map” instead of “mapValues”.
>>
>> Regards,
>>
>> Roland
>

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland