Skip to content

add Chinese translation document #280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
8471fbe
Chinese Translation
Jan 2, 2014
af20f32
Update index.md
imsingo Jan 2, 2014
a72f45e
Update index.md
imsingo Jan 2, 2014
973e20a
Update index.md
imsingo Jan 2, 2014
768aa1e
Update String_Interpolation.md
imsingo Jan 2, 2014
7180dcd
Update Implicit-Classes.md
imsingo Jan 2, 2014
2bfbd8f
Update Futures-and-Promises.md
imsingo Jan 2, 2014
e0fa922
Update Concrete_Parallel_Collection_Classes.md
imsingo Jan 2, 2014
f1edb89
Update index.md
imsingo Jan 2, 2014
caf17c0
Update Migrating_from_Scala_2_7.md
imsingo Jan 2, 2014
16cf83a
Update Conversions_Between_Java_and_Scala_Collections.md
imsingo Jan 2, 2014
7a21f8d
Update Creating_Collections_From_Scratch.md
imsingo Jan 2, 2014
ca11562
Update Iterators.md
imsingo Jan 2, 2014
f5ca126
Update Views.md
imsingo Jan 2, 2014
03a92e0
Update Equality.md
imsingo Jan 2, 2014
48defa1
Update Performance_Characteristics.md
imsingo Jan 2, 2014
b6afc8f
Update Strings.md
imsingo Jan 2, 2014
c2a030a
Update Arrays.md
imsingo Jan 2, 2014
609895b
Update Concrete_Mutable_Collection_Classes.md
imsingo Jan 2, 2014
df03719
Update Concrete_Immutable_Collection_Classes.md
imsingo Jan 2, 2014
821d1f9
Update Maps.md
imsingo Jan 2, 2014
eee4044
Update Sets.md
imsingo Jan 2, 2014
09bbf57
Update The_sequence_traits.md
imsingo Jan 2, 2014
70d1cfe
Update Trait_Iterable.md
imsingo Jan 2, 2014
2811b67
Update Trait_Traversable.md
imsingo Jan 2, 2014
97a1c64
Update Mutable_and_Immutable_Collections.md
imsingo Jan 2, 2014
b09c7ed
Update Introduction.md
imsingo Jan 2, 2014
558d001
Update The_Scala_Actors_API.md
imsingo Jan 2, 2014
9962766
Update The_Architecture_of_Scala_Collections.md
imsingo Jan 2, 2014
8dfed6e
Update Measuring_Performance.md
imsingo Jan 2, 2014
b4252a4
Update Configuring_Parallel_Collections.md
imsingo Jan 2, 2014
b605287
Update Creating_Custom_Parallel_Collections.md
imsingo Jan 2, 2014
7c51bf3
Update Architecture_of_the_Parallel_Collections_Library.md
imsingo Jan 2, 2014
03353b8
Update Concurrent_Tries.md
imsingo Jan 2, 2014
735fb81
Update Parallel_Collection_Conversions.md
imsingo Jan 2, 2014
c2b266a
Update Overview.md
imsingo Jan 2, 2014
2ff372d
Update Value-Classes-and-Universal-Traits.md
imsingo Jan 2, 2014
32848fc
Update The-Scala-Actors-Migration-Guide.md
imsingo Jan 2, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions cn/overviews/Thanks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
layout: guides-Thanks
language: cn
title: 致谢名单
---

2013年10月份起,CSDN CODE开始组织志愿者翻译Scala官方文档。计划翻译的文档主要为Scala官网上overview部分的内容,包含以下部分:

- The Scala Actors Migration Guide
- Value Classes and Universal Traits
- String Interpolation NEW IN 2.10
- Implicit Classes AVAILABLE
- Futures and Promises NEW IN 2.10
- Scala’s Parallel Collections Library
- The Architecture of Scala Collections
- The Scala Actors API
- Scala’s Collections Library

经过公开征集、筛选,我们最终组织了二十多位志愿者来进行此项翻译工作。我们并邀请到了国内Scala知名社区“Scala研学社”的两位老师**连城**、**尹绪森**来担任顾问和翻译校对的工作。在此向Scala研学社表示衷心的感谢!

更要特别感谢的是在此次翻译工作中付出辛勤劳动的、广大的翻译志愿者朋友们,他们是:
(以下按姓氏拼音排序)
姓名 CSDN ID
陈骏 [jacty0219](https://code.csdn.net/jacty0219)
陈幸 Meteor2520
董泉 dqsweet
何乃梧 [yuyi20112011](https://code.csdn.net/yuyi20112011)
黄越勇 aptweasel
赖正兴 laizx
李奕飞 fancylee
林君 a455642158
刘国锋 [iceongrass](https://code.csdn.net/iceongrass)
吕浩志 lvhaozhi
聂雪珲 blueforgetmenot
潘栋华
潘义文 Caidaoqq
王金岩 i9901028
王雨施
熊杰 [xiaoxiong345064855](https://code.csdn.net/xiaoxiong345064855)
杨志斌 qwewegfd
张冰 usen521
张明明 [a775901421](https://code.csdn.net/a775901421)
张欣 [email protected]
周逸灵 pastgift

感谢大家的辛勤劳动!
我们已将经过最终校审的Scala文档中文版上传在此文档项目中,欢迎各位阅读、指正。如果您发现翻译稿件中有什么错误或问题,可以在此项目中给我们留言,或者直接派生、修改后提交合并请求给我们。谢谢!
118 changes: 118 additions & 0 deletions cn/overviews/collections/Arrays.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
layout: overview-large
title: 数组

disqus: true

partof: collections
num: 10
languages: [cn]
---

在Scala中,[数组](http://www.scala-lang.org/api/2.10.0/scala/Array.html)是一种特殊的collection。一方面,Scala数组与Java数组是一一对应的。即Scala数组Array[Int]可看作Java的Int[],Array[Double]可看作Java的double[],以及Array[String]可看作Java的String[]。但Scala数组比Java数组提供了更多内容。首先,Scala数组是一种泛型。即可以定义一个Array[T],T可以是一种类型参数或抽象类型。其次,Scala数组与Scala序列是兼容的 - 在需要Seq[T]的地方可由Array[T]代替。最后,Scala数组支持所有的序列操作。这里有个实际的例子:

scala> val a1 = Array(1, 2, 3)
a1: Array[Int] = Array(1, 2, 3)
scala> val a2 = a1 map (_ * 3)
a2: Array[Int] = Array(3, 6, 9)
scala> val a3 = a2 filter (_ % 2 != 0)
a3: Array[Int] = Array(3, 9)
scala> a3.reverse
res1: Array[Int] = Array(9, 3)

既然Scala数组表现的如同Java的数组,那么Scala数组这些额外的特性是如何运作的呢?实际上,Scala 2.8与早期版本在这个问题的处理上有所不同。早期版本中执行打包/解包过程时,Scala编译器做了一些“神奇”的包装/解包的操作,进行数组与序列对象之间互转。其中涉及到的细节相当复杂,尤其是创建一个新的泛型类型数组Array[T]时。一些让人迷惑的罕见实例以及数组操作的性能都是不可预测的。

Scala 2.8设计要简单得多,其数组实现系统地使用隐式转换,从而基本去除了编译器的特殊处理。Scala 2.8中数组不再看作序列,因为本地数组的类型不是Seq的子类型。而是在数组和 `scala.collection.mutable.WrappedArray`这个类的实例之间隐式转换,后者则是Seq的子类。这里有个例子:

scala> val seq: Seq[Int] = a1
seq: Seq[Int] = WrappedArray(1, 2, 3)
scala> val a4: Array[Int] = s.toArray
a4: Array[Int] = Array(1, 2, 3)
scala> a1 eq a4
res2: Boolean = true

上面的例子说明数组与序列是兼容的,因为数组可以隐式转换为WrappedArray。反之可以使用Traversable提供的toArray方法将WrappedArray转换为数组。REPL最后一行表明,隐式转换与toArray方法作用相互抵消。

数组还有另外一种隐式转换,不需要将数组转换成序列,而是简单地把所有序列的方法“添加”给数组。“添加”其实是将数组封装到一个ArrayOps类型的对象中,后者支持所有序列的方法。ArrayOps对象的生命周期通常很短暂,不调用序列方法的时候基本不会用到,其内存也可以回收。现代虚拟机一般不会创建这个对象。

在接下来REPL中展示数组的这两种隐式转换的区别:

scala> val seq: Seq[Int] = a1
seq: Seq[Int] = WrappedArray(1, 2, 3)
scala> seq.reverse
res2: Seq[Int] = WrappedArray(3, 2, 1)
scala> val ops: collection.mutable.ArrayOps[Int] = a1
ops: scala.collection.mutable.ArrayOps[Int] = [I(1, 2, 3)
scala> ops.reverse
res3: Array[Int] = Array(3, 2, 1)

注意seq是一个WrappedArray,seq调用reverse方法也会得到一个WrappedArray。这是没问题的,因为封装的数组就是Seq,在任意Seq上调用reverse方法都会得到Seq。反之,变量ops属于ArrayOps这个类,对其调用reverse方法得到一个数组,而不是Seq。

上例直接使用ArrayOps仅为了展示其与WrappedArray的区别,这种用法非常不自然。一般情况下永远不要实例化一个ArrayOps,而是在数组上调用Seq的方法:

scala> a1.reverse
res4: Array[Int] = Array(3, 2, 1)

ArrayOps的对象会通过隐式转换自动的插入,因此上述的代码等价于

scala> intArrayOps(a1).reverse
res5: Array[Int] = Array(3, 2, 1)

这里的intArrayOps就是之前例子中插入的隐式转换。这里引出一个疑问,上面代码中,编译器为何选择了intArrayOps而不是WrappedArray做隐式转换?毕竟,两种转换都是将数组映射到支持reverse方法的类型,并且指定输入。答案是两种转换是有优先级次序的,ArrayOps转换比WrappedArray有更高的优先级。前者定义在Predef对象中,而后者定义在继承自Predef的`scala.LowPritoryImplicits`类中。子类、子对象中隐式转换的优先级低于基类。所以如果两种转换都可用,Predef中的会优先选取。字符串的情况也是如此。

数组与序列兼容,并支持所有序列操作的方法,你现在应该已经了然于胸。那泛型呢?在Java中你不可以定义一个以T为类型参数的`T[]`。那么Scala的`Array[T]`是如何做的呢?事实上一个像`Array[T] `的泛型数组在运行时态可任意为Java的八个原始数组类型像`byte[]`, `short[]`, `char[]`, `int[]`, `long[]`, `float[]`, `double[]`, `boolean[]`,甚至它可以是一个对象数组。最常见的运行时态类型是AnyRef ,它包括了所有的这些类型(相当于java.lang.Object),因此这样的类型可以通过Scala编译器映射到`Array[T]`.在运行时,当`Array[T]`类型的数组元素被访问或更新时,就会有一个序列的类型测试用于确定真正的数组类型,随后就是java中的正确的数组操作。这些类型测试会影响数组操作的效率。这意味着如果你需要更大的性能,你应该更喜欢具体而明确的泛型数组。代表通用的泛型数组是不够的,因此,也必然有一种方式去创造泛型数组。这是一个更难的问题,需要一点点的帮助你。为了说明这个问题,考虑下面用一个通用的方法去创造数组的尝试。

//这是错的!
def evenElems[T](xs: Vector[T]): Array[T] = {
val arr = new Array[T]((xs.length + 1) / 2)
for (i <- 0 until xs.length by 2)
arr(i / 2) = xs(i)
arr
}

evenElems方法返回一个新数组,该数组包含了参数向量xs的所有元素甚至在向量中的位置。evenElems 主体的第一行构建了结果数组,将相同元素类型作为参数。所以根据T的实际类型参数,这可能是一个`Array[Int]`,或者是一个`Array[Boolean]`,或者是一个在java中有一些其他基本类型的数组,或者是一个有引用类型的数组。但是这些类型有不同的运行时表达,那么Scala如何在运行时选择正确的呢?事实上,它不是基于信息传递做的,因为与类型参数T相对应的实际类型在运行时已被抹去。这就是为什么你在编译上面的代码时会出现如下的错误信息:

error: cannot find class manifest for element type T
val arr = new Array[T]((arr.length + 1) / 2)
^
这里需要你做的就是通过提供一些运行时的实际元素类型参数的线索来帮助编译器处理。这个运行时的提示采取的形式是一个`scala.reflect.ClassManifest`类型的类声明。一个类声明就是一个类型描述对象,给对象描述了一个类型的顶层类。另外,类声明也有`scala.reflect.Manifest`类型的所有声明,它描述了类型的各个方面。但对于数组创建而言,只需要提供类声明。

如果你指示编译器那么做它就会自动的构建类声明。“指示”意味着你决定一个类声明作为隐式参数,像这样:

def evenElems[T](xs: Vector[T])(implicit m: ClassManifest[T]): Array[T] = ...

使用一个替换和较短的语法。通过用一个上下文绑定你也可以要求类型与一个类声明一起。这种方式是跟在一个冒号类型和类名为ClassManifest的后面,想这样:

// this works
def evenElems[T: ClassManifest](xs: Vector[T]): Array[T] = {
val arr = new Array[T]((xs.length + 1) / 2)
for (i <- 0 until xs.length by 2)
arr(i / 2) = xs(i)
arr
}

这两个evenElems的修订版本意思是完全相同的。当Array[T] 构造时,在任何情况下会发生的是,编译器会寻找类型参数T的一个类声明,这就是说,它会寻找ClassManifest[T]一个隐式类型的值。如果如此的一个值被发现,声明会用来构造正确的数组类型。否则,你就会看到一个错误信息像上面一样。

下面是一些使用evenElems 方法的REPL 交互。

scala> evenElems(Vector(1, 2, 3, 4, 5))
res6: Array[Int] = Array(1, 3, 5)
scala> evenElems(Vector("this", "is", "a", "test", "run"))
res7: Array[java.lang.String] = Array(this, a, run)

在这两种情况下,Scala编译器自动的为元素类型构建一个类声明(首先,Int,然后String)并且通过它传递evenElems 方法的隐式参数。编译器可以对所有的具体类型构造,但如果论点本身是另一个没有类声明的类型参数就不可以。例如,下面的错误:

scala> def wrap[U](xs: Array[U]) = evenElems(xs)
<console>:6: error: could not find implicit value for
证明类型ClassManifest[U]的参数
def wrap[U](xs: Array[U]) = evenElems(xs)
^
这里所发生的是,evenElems 需要一个类型参数U的类声明,但是没有发现。这种情况下的解决方案是,当然,是为了U的另一个隐式类声明。所以下面起作用了:

scala> def wrap[U: ClassManifest](xs: Array[U]) = evenElems(xs)
wrap: [U](xs: Array[U])(implicit evidence$1: ClassManifest[U])Array[U]

这个实例还显示在定义U的上下文绑定里这仅是一个简短的隐式参数命名为`ClassManifest[U]`类型的`evidence$1`。

总结,泛型数组创建需要类声明。所以每当创建一个类型参数T的数组,你还需要提供一个T的隐式类声明。最简单的方法是声明类型参数与ClassManifest的上下文绑定,如 `[T: ClassManifest]`。

Loading