@@ -18,7 +18,7 @@ language: ja
18
18
scala> val a3 = a2 filter (_ % 2 != 0)
19
19
a3: Array[Int] = Array(3, 9)
20
20
scala> a3.reverse
21
- res1 : Array[Int] = Array(9, 3)
21
+ res0 : Array[Int] = Array(9, 3)
22
22
23
23
Scala の配列は Java の配列で実装されているのに、どのようにして新たな機能をサポートしてるのだろうか。実は、Scala 2.8 とその前のバージョンではその問に対する答が変わってくる。以前は Scala のコンパイラが、ボックス化 (boxing) とボックス化解除 (unboxing) と呼ばれる「魔法」により配列と ` Seq ` オブジェクトの間を変換していた。この詳細は、特にジェネリック型の ` Array[T] ` が作成された場合、非常に複雑なものとなる。不可解な特殊ケースなどもあり、配列演算の性能特性は予想不可能なものとなった。
24
24
@@ -29,7 +29,7 @@ Scala 2.8 の設計はより単純なものだ。ほぼ全てのコンパイラ
29
29
scala> val a4: Array[Int] = s.toArray
30
30
a4: Array[Int] = Array(1, 2, 3)
31
31
scala> a1 eq a4
32
- res2 : Boolean = true
32
+ res1 : Boolean = true
33
33
34
34
上記のやりとりは、配列から ` WrappedArray ` への暗黙の変換があるため、配列と列に互換性があることを示す。` WrappedArray ` から ` Array ` へ逆の方向に変換するには、` Traversable ` に定義されている ` toArray ` メソッドを使うことで実現できる。上記の REPL の最後の行は、ラッピングした後、` toArray ` でそれを解除したときに、同一の配列が得られることを示す。
35
35
@@ -77,7 +77,7 @@ Scala 2.8 の設計はより単純なものだ。ほぼ全てのコンパイラ
77
77
78
78
error: cannot find class manifest for element type T
79
79
val arr = new Array[T]((arr.length + 1) / 2)
80
- ^
80
+ ^
81
81
82
82
あなたがコンパイラを手伝ってあげて、` evenElems ` の型パタメータの実際の型が何であるかの実行時のヒントを提供することが必要とされている。この実行時のヒントは ` scala.reflect.ClassManifest `
83
83
型の** クラスマニフェスト** という形をとる。クラスマニフェストとは、型の最上位クラスが何であるかを記述する型記述オブジェクトだ。型に関するあらゆる事を記述する ` scala.reflect.Manifest ` 型の完全マニフェストというものもある。配列の作成にはクラスマニフェストで十分だ。
@@ -107,15 +107,15 @@ Scala コンパイラは、指示を出すだけでクラスマニフェスト
107
107
108
108
両者の場合とも、Scala コンパイラは要素型 (` Int ` 、そして ` String ` ) のクラスマニフェストを自動的に構築して、` evenElems ` メソッドの暗黙のパラメータに渡した。コンパイラは全ての具象型についてクラスマニフェストを構築できるが、引数そのものがクラスマニフェストを持たない型パラメータである場合はそれができない。以下に失敗例を示す:
109
109
110
- scala> def wrap[U](xs: Array [U]) = evenElems(xs)
111
- <console>:6: error: could not find implicit value for
112
- evidence parameter of type ClassManifest [U]
113
- def wrap[U](xs: Array[U]) = evenElems(xs)
114
- ^
110
+ scala> def wrap[U](xs: Vector [U]) = evenElems(xs)
111
+ <console>:6: error: No ClassManifest available for U.
112
+ def wrap [U](xs: Vector[U]) = evenElems(xs)
113
+ ^
114
+
115
115
何が起こったかというと、` evenElems ` は型パラメータ ` U ` に関するクラスマニフェストを要求するが、見つからなかったのだ。当然この場合は、` U ` に関する暗黙のクラスマニフェストを要求することで解決するため、以下は成功する:
116
116
117
- scala> def wrap[U: ClassManifest](xs: Array [U]) = evenElems(xs)
118
- wrap: [U](xs: Array [U])(implicit evidence$1: ClassManifest[U])Array[U]
117
+ scala> def wrap[U: ClassManifest](xs: Vector [U]) = evenElems(xs)
118
+ wrap: [U](xs: Vector [U])(implicit evidence$1: ClassManifest[U])Array[U]
119
119
120
120
この例から、` U ` の定義の context bound 構文は ` evidence$1 ` と呼ばれる ` ClassManifest[U] ` 型の暗黙のパラメータの略記法であることが分かる。
121
121
0 commit comments