diff --git a/ja/overviews/collections/arrays.md b/ja/overviews/collections/arrays.md index 89d613a459..3c5b0c4425 100644 --- a/ja/overviews/collections/arrays.md +++ b/ja/overviews/collections/arrays.md @@ -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]` が作成された場合、非常に複雑なものとなる。不可解な特殊ケースなどもあり、配列演算の性能特性は予想不可能なものとなった。 @@ -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` でそれを解除したときに、同一の配列が得られることを示す。 @@ -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` 型の完全マニフェストというものもある。配列の作成にはクラスマニフェストで十分だ。 @@ -107,15 +107,15 @@ Scala コンパイラは、指示を出すだけでクラスマニフェスト 両者の場合とも、Scala コンパイラは要素型 (`Int`、そして `String`) のクラスマニフェストを自動的に構築して、`evenElems` メソッドの暗黙のパラメータに渡した。コンパイラは全ての具象型についてクラスマニフェストを構築できるが、引数そのものがクラスマニフェストを持たない型パラメータである場合はそれができない。以下に失敗例を示す: - scala> def wrap[U](xs: Array[U]) = evenElems(xs) - :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) + :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]` 型の暗黙のパラメータの略記法であることが分かる。 diff --git a/overviews/collections/arrays.md b/overviews/collections/arrays.md index 423b877423..e698f2118b 100644 --- a/overviews/collections/arrays.md +++ b/overviews/collections/arrays.md @@ -18,7 +18,7 @@ languages: [ja, 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) Given that Scala arrays are represented just like Java arrays, how can these additional features be supported in Scala? In fact, the answer to this question differs between Scala 2.8 and earlier versions. Previously, the Scala compiler somewhat "magically" wrapped and unwrapped arrays to and from `Seq` objects when required in a process called boxing and unboxing. The details of this were quite complicated, in particular when one created a new array of generic type `Array[T]`. There were some puzzling corner cases and the performance of array operations was not all that predictable. @@ -29,7 +29,7 @@ The Scala 2.8 design is much simpler. Almost all compiler magic is gone. Instead scala> val a4: Array[Int] = seq.toArray a4: Array[Int] = Array(1, 2, 3) scala> a1 eq a4 - res2: Boolean = true + res1: Boolean = true The interaction above demonstrates that arrays are compatible with sequences, because there's an implicit conversion from arrays to `WrappedArray`s. To go the other way, from a `WrappedArray` to an `Array`, you can use the `toArray` method defined in `Traversable`. The last REPL line above shows that wrapping and then unwrapping with `toArray` gives the same array you started with. @@ -74,7 +74,8 @@ The `evenElems` method returns a new array that consist of all elements of the a error: cannot find class manifest for element type T val arr = new Array[T]((arr.length + 1) / 2) - ^ + ^ + What's required here is that you help the compiler out by providing some runtime hint what the actual type parameter of `evenElems` is. This runtime hint takes the form of a class manifest of type `scala.reflect.ClassManifest`. A class manifest is a type descriptor object which describes what the top-level class of a type is. Alternatively to class manifests there are also full manifests of type `scala.reflect.Manifest`, which describe all aspects of a type. But for array creation, only class manifests are needed. The Scala compiler will construct class manifests automatically if you instruct it to do so. "Instructing" means that you demand a class manifest as an implicit parameter, like this: @@ -102,15 +103,15 @@ Here is some REPL interaction that uses the `evenElems` method. In both cases, the Scala compiler automatically constructed a class manifest for the element type (first, `Int`, then `String`) and passed it to the implicit parameter of the `evenElems` method. The compiler can do that for all concrete types, but not if the argument is itself another type parameter without its class manifest. For instance, the following fails: - scala> def wrap[U](xs: Array[U]) = evenElems(xs) - :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) + :6: error: No ClassManifest available for U. + def wrap[U](xs: Vector[U]) = evenElems(xs) + ^ + What happened here is that the `evenElems` demands a class manifest for the type parameter `U`, but none was found. The solution in this case is, of course, to demand another implicit class manifest for `U`. So the following works: - 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] This example also shows that the context bound in the definition of `U` is just a shorthand for an implicit parameter named here `evidence$1` of type `ClassManifest[U]`. diff --git a/zh-cn/overviews/collections/arrays.md b/zh-cn/overviews/collections/arrays.md index 35da9aa0f2..bb2f9685cc 100644 --- a/zh-cn/overviews/collections/arrays.md +++ b/zh-cn/overviews/collections/arrays.md @@ -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]时。一些让人迷惑的罕见实例以及数组操作的性能都是不可预测的。 @@ -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方法作用相互抵消。 @@ -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`类型的所有声明,它描述了类型的各个方面。但对于数组创建而言,只需要提供类声明。 如果你指示编译器那么做它就会自动的构建类声明。“指示”意味着你决定一个类声明作为隐式参数,像这样: @@ -102,15 +103,15 @@ evenElems方法返回一个新数组,该数组包含了参数向量xs的所有 在这两种情况下,Scala编译器自动的为元素类型构建一个类声明(首先,Int,然后String)并且通过它传递evenElems 方法的隐式参数。编译器可以对所有的具体类型构造,但如果论点本身是另一个没有类声明的类型参数就不可以。例如,下面的错误: - scala> def wrap[U](xs: Array[U]) = evenElems(xs) - :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) + :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`。