scala列表映射vs mapConserve

Win*_*tet 8 scala

我试图理解mapConserve,它被称为"像xs map f,但如果函数f将所有元素映射到自己,则返回xs不变",来自List.然而,它正在发出错误.

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)
                   ^
Run Code Online (Sandbox Code Playgroud)

mapConserve代码应该满足(A)=> A函数.如果不是,它仍然应该满足(A)=> B函数,因为类型A可以是其自身的子类型和超类型.请赐教mapConserve的目的和错误.

4e6*_*4e6 19

实际上,mapConserve定义为

def mapConserve[A <: AnyRef](xs: List[A])(f: A => A): List[A]
def mapConserve[B >: A <: AnyRef](f: A => B): List[B]
Run Code Online (Sandbox Code Playgroud)

所以A应该是一个子类型AnyRef.Int是一个AnyVal带来错误的子类型.

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)
Run Code Online (Sandbox Code Playgroud)

更新:

mapsc之间的唯一区别mapConserve,如scaladoc中所描述的:

通过将函数应用于此列表的所有元素来构建新列表.与xs map f类似,但如果函数f将所有元素映射到自身(由eq确定),则返回xs不变.

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
Run Code Online (Sandbox Code Playgroud)

xs mapConserve identity在我简单的基准大约快五倍.

  • 但是mapConserve的用例是什么?你应该在哪里以及为什么使用它而不是简单的地图? (10认同)