【转】Scala 片段2:List的操作符魔法

原文链接 http://www.ituring.com.cn/article/131439

 

本文翻译自:Scala snippets 2: List symbol magic fairjm@ituring


Scala的每一个操作符都可以是函数,所以重载操作符(实际上不是真正的重载操作符,毕竟操作符都已经是方法了)

是一件非常简单并且在很多库中都能看见的事。在这个片段中,我们将探讨一些让列表操作更加简单的方法重载。

让我们从++操作符开始。首先,就像我们一直做的那样,让我们来创建一个列表:

scala> val list = 0 until 10 toList
list: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> val list2 = 10 to 0 by -1 toList
list2: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

然后大致浏览下来自 http://www.scala-lang.org/api/2.11.1/index.html#scala.collection.immutable.List 的一些操作:

第一个操作符是++。我们可以用这个操作符把两个列表连接在一起,并且返回一个新的列表:

scala> val list3 = list ++ list2
list3: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

scala> val list3 = list2 ++ list
list3: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

注意你并不需要保证列表是相同类型的。Scala会自动选择最相关的父类:

scala> val list1 = 0 to 10 toList
list1: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val list2 = 10 to 0 by -1 toList
list2: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

scala> val list3 = list1.asInstanceOf[List[Double]]
list3: List[Double] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> list3 ++ list2
res4: List[AnyVal] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

你可以看到最后的返回是AnyVal类型的列表,这是对于IntDouble最常见的父类。

既然我们已经看过++了,让我们来看看和++看起来最相似的++:。这个操作符和++有着相同的语义,

不同的地方是结果的类型在++中取决于左操作数而这个操作符取决于右操作数:

scala> vector1
res14: Vector[Int] = Vector(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

scala> list1
res15: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vector1 ++ list1
res16: scala.collection.immutable.Vector[Int] = Vector(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> vector1 ++: list1
res17: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

接下来的两个操作符:++:可以让我们向后和向前对列表增加新的元素:

scala> 999 +: list1
res27: List[Int] = List(999, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> list1 :+ 999
res28: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 999)

还有什么?:::::都是对列表之前增加一些东西的函数。::操作符增加单个元素,而:::操作符增加一个列表。

所以基本上他们是和+:++操作一样的。主要的区别是+:++可以被用于Traversable,但:::::只能用于列表。

scala> 11 +: list1
res38: List[Int] = List(11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> list1
res39: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> 11 +: list1
res40: List[Int] = List(11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> list2
res41: List[Int] = List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

scala> list1 ::: list2
res43: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

:\/:用于折叠操作(看这里)。:\从右至左折叠,而/:从左至右:

scala> list1
res50: List[Int] = List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> (1 /: list1)((r,i) => {println(i);i+r})
0
1
2
3
4
5
6
7
8
9
10
res51: Int = 56

scala> (list1 :\ 1)((i,r) => {println(i);i+r})
10
9
8
7
6
5
4
3
2
1
0
res52: Int = 56

你可以看到折叠的方向决定了元素是从前往后还是从后往前处理的。

这就是这个片段的全部。

 

posted on 2015-08-15 22:57  develooop  阅读(269)  评论(0编辑  收藏  举报

导航

AmazingCounters.com