Skip to content

Commit

Permalink
same fixes as in the english version
Browse files Browse the repository at this point in the history
  • Loading branch information
Philippus committed Feb 12, 2017
1 parent 406e8f0 commit 1d206c4
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 20 deletions.
20 changes: 10 additions & 10 deletions ja/overviews/collections/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ language: ja
scala> val a3 = a2 filter (_ % 2 != 0)
a3: Array[Int] = Array(3, 9)
scala> a3.reverse
res1: Array[Int] = Array(9, 3)
res0: Array[Int] = Array(9, 3)

Scala の配列は Java の配列で実装されているのに、どのようにして新たな機能をサポートしてるのだろうか。実は、Scala 2.8 とその前のバージョンではその問に対する答が変わってくる。以前は Scala のコンパイラが、ボックス化 (boxing) とボックス化解除 (unboxing) と呼ばれる「魔法」により配列と `Seq` オブジェクトの間を変換していた。この詳細は、特にジェネリック型の `Array[T]` が作成された場合、非常に複雑なものとなる。不可解な特殊ケースなどもあり、配列演算の性能特性は予想不可能なものとなった。

Expand All @@ -29,7 +29,7 @@ Scala 2.8 の設計はより単純なものだ。ほぼ全てのコンパイラ
scala> val a4: Array[Int] = s.toArray
a4: Array[Int] = Array(1, 2, 3)
scala> a1 eq a4
res2: Boolean = true
res1: Boolean = true

上記のやりとりは、配列から `WrappedArray` への暗黙の変換があるため、配列と列に互換性があることを示す。`WrappedArray` から `Array` へ逆の方向に変換するには、`Traversable` に定義されている `toArray` メソッドを使うことで実現できる。上記の REPL の最後の行は、ラッピングした後、`toArray` でそれを解除したときに、同一の配列が得られることを示す。

Expand Down Expand Up @@ -77,7 +77,7 @@ Scala 2.8 の設計はより単純なものだ。ほぼ全てのコンパイラ

error: cannot find class manifest for element type T
val arr = new Array[T]((arr.length + 1) / 2)
^
^

あなたがコンパイラを手伝ってあげて、`evenElems` の型パタメータの実際の型が何であるかの実行時のヒントを提供することが必要とされている。この実行時のヒントは `scala.reflect.ClassManifest`
型の**クラスマニフェスト**という形をとる。クラスマニフェストとは、型の最上位クラスが何であるかを記述する型記述オブジェクトだ。型に関するあらゆる事を記述する `scala.reflect.Manifest` 型の完全マニフェストというものもある。配列の作成にはクラスマニフェストで十分だ。
Expand Down Expand Up @@ -107,15 +107,15 @@ Scala コンパイラは、指示を出すだけでクラスマニフェスト

両者の場合とも、Scala コンパイラは要素型 (`Int`、そして `String`) のクラスマニフェストを自動的に構築して、`evenElems` メソッドの暗黙のパラメータに渡した。コンパイラは全ての具象型についてクラスマニフェストを構築できるが、引数そのものがクラスマニフェストを持たない型パラメータである場合はそれができない。以下に失敗例を示す:

scala> def wrap[U](xs: Array[U]) = evenElems(xs)
<console>:6: error: could not find implicit value for
evidence parameter of type ClassManifest[U]
def wrap[U](xs: Array[U]) = evenElems(xs)
^
scala> def wrap[U](xs: Vector[U]) = evenElems(xs)
<console>:6: error: No ClassManifest available for U.
def wrap[U](xs: Vector[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]
scala> def wrap[U: ClassManifest](xs: Vector[U]) = evenElems(xs)
wrap: [U](xs: Vector[U])(implicit evidence$1: ClassManifest[U])Array[U]

この例から、`U` の定義の context bound 構文は `evidence$1` と呼ばれる `ClassManifest[U]` 型の暗黙のパラメータの略記法であることが分かる。

Expand Down
21 changes: 11 additions & 10 deletions zh-cn/overviews/collections/arrays.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ language: zh-cn
scala> val a3 = a2 filter (_ % 2 != 0)
a3: Array[Int] = Array(3, 9)
scala> a3.reverse
res1: Array[Int] = Array(9, 3)
res0: Array[Int] = Array(9, 3)

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

Expand All @@ -29,7 +29,7 @@ Scala 2.8设计要简单得多,其数组实现系统地使用隐式转换,
scala> val a4: Array[Int] = s.toArray
a4: Array[Int] = Array(1, 2, 3)
scala> a1 eq a4
res2: Boolean = true
res1: Boolean = true

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

Expand Down Expand Up @@ -74,7 +74,8 @@ evenElems方法返回一个新数组,该数组包含了参数向量xs的所有

error: cannot find class manifest for element type T
val arr = new Array[T]((arr.length + 1) / 2)
^
^

这里需要你做的就是通过提供一些运行时的实际元素类型参数的线索来帮助编译器处理。这个运行时的提示采取的形式是一个`scala.reflect.ClassManifest`类型的类声明。一个类声明就是一个类型描述对象,给对象描述了一个类型的顶层类。另外,类声明也有`scala.reflect.Manifest`类型的所有声明,它描述了类型的各个方面。但对于数组创建而言,只需要提供类声明。

如果你指示编译器那么做它就会自动的构建类声明。“指示”意味着你决定一个类声明作为隐式参数,像这样:
Expand Down Expand Up @@ -102,15 +103,15 @@ evenElems方法返回一个新数组,该数组包含了参数向量xs的所有

在这两种情况下,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)
^
scala> def wrap[U](xs: Vector[U]) = evenElems(xs)
<console>:6: error: No ClassManifest available for U.
def wrap[U](xs: Vector[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]
scala> def wrap[U: ClassManifest](xs: Vector[U]) = evenElems(xs)
wrap: [U](xs: Vector[U])(implicit evidence$1: ClassManifest[U])Array[U]

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

Expand Down

0 comments on commit 1d206c4

Please sign in to comment.