Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala List map vs mapConserve

Tags:

scala

I am trying to understand mapConserve, which is said to be "Like xs map f, but returns xs unchanged if function f maps all elements to themselves," from List. Yet, it is giving out error.

def map [B] (f: (A) ⇒ B): List[B]
def mapConserve (f: (A) ⇒ A): List[A]
def mapConserve [B >: A <: AnyRef] (f: (A) ⇒ B): List[B]


scala> list map (x=>x)
res105: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> list mapConserve (x=>x)
<console>:12: error: inferred type arguments [Int] do not conform to method mapConserve's type parameter bounds [B >: Int <: AnyRef]
              list mapConserve (x=>x)
                   ^

The mapConserve code should satisfy the (A) => A function. If not, it still should satisfy the (A) => B function, since type A can be subtype and supertype of itself. Please enlighten me the purpose of mapConserve and the error.

like image 612
Win Myo Htet Avatar asked Dec 23 '11 05:12

Win Myo Htet


1 Answers

Actually, mapConserve is defined as

def mapConserve[A <: AnyRef](xs: List[A])(f: A => A): List[A]
def mapConserve[B >: A <: AnyRef](f: A => B): List[B]

so A should be a subtype of AnyRef. Int is a subtype of AnyVal, that brings an error.

scala> val l = List("foo", "bar", "baz")
l: List[java.lang.String] = List(foo, bar, baz)

scala> l.mapConserve(_.toUpperCase)
res4: List[java.lang.String] = List(FOO, BAR, BAZ)

scala> l.mapConserve(identity)
res5: List[java.lang.String] = List(foo, bar, baz)

Update:

The only difference between map and mapConserve, as it is described in the scaladoc:

Builds a new list by applying a function to all elements of this list. Like xs map f, but returns xs unchanged if function f maps all elements to themselves (as determined by eq).

scala> val xs = List.fill(1000000)("foo")
xs: List[java.lang.String] = List(foo, foo,...)

scala> xs.map(identity) eq xs
res48: Boolean = false

scala> xs.mapConserve(identity) eq xs
res49: Boolean = true

And xs mapConserve identity is about five times faster in my simple benchmark.

like image 192
4e6 Avatar answered Nov 10 '22 09:11

4e6