前ページ | トップページ | 次ページ

6階:型

型の様々

型引数付き型(配列等の構造型)、タプル型、関数型の表明方法については既に触れた。Scalaにおいて、その他に簡潔に表明可能な型は:シングルトンの型は「シングルトン名.type」、型メンバは「クラスまたはトレイト名#型メンバ名」もしくは「シングルトンまたはパッケージ名.型メンバ名」(ペアで無いシングルトン及びパッケージは、型に関しては、それ自体へのアクセスは不可能な暗黙の同名クラスを持つものと見なされる。なお、その型メンバを定義するテンプレートでは「this.型メンバ名」も可(当然、そのテンプレートで定義されている型メンバを指す))。


二項演算型は、言語仕様にも他にも例が無いので私にはよく分からないが、とにかくも「型 識別子 型」で表明される型のことだ。この識別子は「*」以外なら何でも可で、しかし優先順位はどの識別子でも同じであり、ただ「:」で終わるものだけ右からの評価になる、つまり、「:」で終わるものを含まずに左から出現順に評価されるか、あるいは「:」で終わるものだけで右から順に評価されるか、の二通りしかない。いずれ、識別子は左右の型を型引数に持つ型名に等しい。なお、この二項演算型の型の代わりに「_」も可能である(このワイルドカードは普通の型引数、関数型とタプル型でも使える)。

複合型

複合型は、「型」に 「with 型」を複数続けて表明される。これは、それらのすべての型のすべてのメンバを持つものを指す型である。また、最後の型の後ろに波括弧で囲まれた「細別」をも加えて良い:細別はゼロ個以上の宣言あるいは型定義からのみ成り、必須とされるメンバをさらに特定する(なぜかScalaの作者は、この「細別」(refinement)という語を無名クラス定義の波括弧の方にしばしば使っているが、それらは宣言と型定義以外をも含むのであれば、言語仕様におけるこちらの細別とは別物と見なされねばなるまい)。また、複合型は細別だけでも良く、その場合は「AnyRef」が暗黙に前置されているものと見なされる。細別ではオーバーライドにはならない宣言や型定義も指定可能だが、その場合は極端に実行速度が低下することが言語仕様に明記されているので注意されたい。

存在型

存在(existential:述語論理で存在量化、つまり、「少なくとも一つは在る」ことを意味する語)型は、「型 forSome {ゼロ個以上の型宣言及びval宣言}」で表明される:それらの型宣言(のいずれか?)を満す型なら何でもよろしい、という意味である。これのval宣言はシングルトン用で、例えば「T1[x.T2] forSome {val x: T3}」は「T3型に適合する任意のシングルトンの型メンバT2を要素とするT1型」を意味する。しかし、実際のところ複数の型宣言等が使われることはほとんど無く、むしろすぐ次に解説する型引数限定子とともに使われるケースが圧倒的に多い。

型引数限定子

「+型名」は共変(covariant)、「-型名」は反変(contravariant)を指定する。これら無しはScalaでは無変(invariant)である。これはどこでも自由に使えるのでは無く、型自体の型引数においては本質的にそれらと「逆」のところには使えない。一般に、まずトップレベルの型及びテンプレートは必ず共変でなければならない;メソッドの引数の型と返値の型は互いに逆になる(既述したように、メソッドの引数の型は常に反変であり返値は常に共変である);型引数の型とそれを要素とする型は互いに逆になる(左のことはコンストラクタでも同様ということ);反変要素への実引数とそれを要素とする当の型自体とは互いに逆になる(左のことはコンストラクタへの実型引数でも同様ということ);型宣言の定義式、「var」識別子、「クラスまたはトレイト名#型メンバ名」のクラスまたはトレイト名は常に無変;型宣言または型引数とその最低型限定(後述)は互いに逆になる。

最後のは、最低型限定が共変ならそれは「より祖な型に開かれている」意味になるのだから、必然的にその型自体は反変でないと矛盾する;反変ならそれは「より子な型に開かれている」意味なのでやはり必然的にその型自体は共変でないと矛盾する、ということである。なお、シングルトンのprivateな「val」及び「var」識別子とそのペアクラスのメソッドへの型引数ではこの逆かどうかのチェックは行なわれない。


「>: 型名」は最低型を、「<: 型名」は最大型を限定する;「<% 型名」すなわちビュー型限定は後述するが、この三つはこの順で記述されねばならないので一応ここで紹介しておく。これらは型引数の各々にでは無く、最後に各々無しまたは一つだけ置かれなければならない。また最初の二つに限っては型宣言のその宣言される型自体(存在型のそれをも含む)を修飾でき、この場合無しは各々「>: Nothing」と「<: Any」が指定されたものと見なされる。また存在型に関して、「型[_ >: L <: U]」は「型[型変数] forSome {type 型変数 >: L <: U}」に等しい。

最低型というのは、これよりも子な型はエラーになり、最大型も同様にこれよりも祖な型はエラーになるという意味で、もっぱら型変数とともに使われて、いわゆるジェネリクスにおけるより精密な型チェックを可能ならしめるものである。

型宣言、型定義、型引数

型定義は「type 識別子[型引数] = 型」で為され(もちろん、型引数は不要なら角括弧ごと省略されて良い)、型宣言はこの右辺の定義式を省略したものである;なお、型引数で使われる型の同時定義はできない、つまり、それはそれで事前に定義または宣言されていなければならない。角括弧は実のところ型名空間のスコープ単位で、ちょうど関数定義の引数名が右辺の同名と同一であるように、型定義の型引数名もやはり右辺の同名と同一である。

型引数は型定義・型宣言の他にも、クラス定義・トレイト定義及び関数・メソッド定義で使うこともできる(クラス定義ではデフォルトコンストラクタへのみ指定可)。その場合、型引数は普通の引数(の場所と見なされる部分;型引数のみで普通の引数が無い場合もあり得る)の直前に置かれ、実際にそれらを呼び出す時に同様に実型引数を指定することになる(が、普通の引数の型から推定可能な場合は実型引数の指定は省略でき、むしろそれが普通である)。

ビュー

ビューは、通常の型変換ではエラーになるような組み合わせにおいて、「元の型 => 必要な型」または「( => 元の型) => 必要な型」となる関数を暗黙名空間から捜し出し、もし在ればそれを適用して型変換を行う、という仕組みである。クラスまたはメソッド定義の型引数に「型1 <% 型2」すなわちビュー型限定が可能であるが、これはその定義に「(implicit 任意匿名: 型1 => 型2)」を追加することの簡略表現で、要するにそのクラス(コンストラクタ)またはメソッドをビュー型変換用として暗黙名空間に登録するに等しい。

仮想クラス

Any、AnyRef、Null、Nothing、Unit、AnyVal及びAnyValの子型(Javaの基本型へのラッパークラス)はソースを持たない、コンパイラの実装内部に散らばっている諸定義の集約から成るいわば仮想クラスとも言うべきものである(「::」ケースクラス(とその暗黙の派生であるシングルトン)はList.scalaに記述されている)。うちNothingとAnyValはマーカーとも呼ぶべきもので実体は無いに等しい;AnyValの子型(なお、UnitもAnyValの子型である)も、Javaの演算子及びそれら子型間の変換メソッド(to型名)を持っているだけで、既に何度も触れているNullとNothingともども、特には解説は不要だろう。AnyとAnyRefに関しては、ユーザクラスで継承する際の参考用に、言語仕様の定める「疑似ソース」を書き写しておく。

abstract class Any {
	def equals(that: Any): Boolean
	def hashCode: Int
	def toString: String
	final def == (that: Any): Boolean =
		if (null eq this) null eq that else this equals that
	final def != (that: Any): Boolean = !(this == that)
	def isInstanceOf[A]: Boolean = this match {
		case x: A => true
		case _ => false
	}
	def asInstanceOf[A]: A = this match {
		case x: A => x
		case _ => if (this eq null) this
			else throw new ClassCastException()
	}
}

最初の三つは宣言のみであり、下位クラスでの定義にその実体は委ねられている。「==」はAnyRef系でいずれかがnullならnullを返し、さもなければequalsの適用に等しいということ。「asInstanceOf」は、ケースパターンでは比較用に暗黙にそのパターンのインスタンスが生成されるのを利用し、マッチ成功=インスタンス生成成功ならそのインスタンスを返す仕組みだ。

class AnyRef extends Any {
	def equals(that: Any): Boolean = this eq that
	final def eq(that: AnyRef): Boolean = 同一参照ならtrue
	final def ne(that: AnyRef): Boolean = !(this eq that)
	def hashCode: Int = thisのメモリアドレス値
	def toString: String = クラス名@16進ハッシュコード値
	final def synchronized[T0](arg0: T0): T0 = Javaでのsynchronized (this){arg0}に等しい
}

AnyRefの実行時実体は対話シェルで確認できるようにjava.lang.Objectであり、ゆえにそのメソッドも持ち合わせている。上記五つのメソッドはだからObjectの継承によるオーバーライドや追加というわけでは無く、Scala側からはあたかもObject自体のメソッドであるかのように見せかける仕組みになっている、つまり、ScalaではAnyRefとObjectは同一である。

リスト型詳細

Javaとは異なるScala(というか関数型言語)的なるものは、再帰リストをその主要データ型としている。他のデータ型はもちろん、Java基本型への追加メソッドも再帰リストをモデル(化)とするものだと言えるのであれば、これについて詳細を把握することはScalaライブラリを理解するための最小限必須な事項だと言えよう。それで、以下ではその祖クラスからたどる形でメソッドの一覧解説を述べる(説明不要なオーバーライドメソッドは省略)。なお、もう一つの重要な型であるタプルは有意味なメソッドが無いので(たった一つ、要素二つのタプルに限りswapという要素入れ替えメソッドが在るだけ)その解説は省略する。


trait Function1[-T1, +R] extends AnyRef


引数一つの関数;再帰データは引数一つの再帰関数の静的表現とも見なせる(個々の再帰が各要素に相当)

def andThen[A](g: (R) => A): (T1) => A
// (f _ andThen g _)(x) == g(f(x));二つの関数を合成する(左から評価)
abstract def apply(v1: T1): R
// 関数本体
def compose[A](g: (A) => T1): (A) => R
// (f _ compose g _)(x) == f(g(x));二つの関数を合成する(右から評価)
override def toString = "<function>"


trait PartialFunction[-A, +B] extends (A) => B


無名ケース関数;再帰データは三つのケース(当要素・次要素へのリンク・無要素)から成る無名関数とも見なせる

abstract def isDefinedAt(x: A): Boolean
// ケースパターンがマッチするならtrue;無名ケース関数ではまずこれが呼ばれてケースのブロックを選択する
def orElse[A1 <: A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1]
// 二つの無名ケース関数を一つのそれとなるように合成する


trait Iterable[+A] extends AnyRef


Iterator化可能とするトレイト

def hasDefiniteSize: Boolean
// Iterableのメソッドの多くは要素数が無限で無いことを前提としている
def isEmpty: Boolean
def toList: List[A]
def toSeq: Seq[A]
def toStream: Stream[A]
// 関数型言語でのStreamは遅延リストのことであって入出力のことでは無い
abstract def elements: Iterator[A]
// 全要素から成るIteratorを返す。Iteratorは再帰処理を考慮していないので関数型言語ではあまり出番は無い
def projection: Projection[A]
// 自己に等しい遅延(non-strict)クラス(ProjectionはIterableの遅延版)へキャストする
def mkString: java.lang.String
// 各要素のtoString表現を結合した文字列を返す
def mkString(sep: java.lang.String): java.lang.String
// 上でsepを区切り文字とする
def mkString(start: java.lang.String,
		sep: java.lang.String,
		end: java.lang.String): java.lang.String
// 上をstart文字列で接頭しend文字列で接尾する
def addString(buf: StringBuilder, sep: java.lang.String): StringBuilder
def addString(buf: StringBuilder,
		start: java.lang.String,
		sep: java.lang.String,
		end: java.lang.String): StringBuilder
def copyToArray[B >: A](xs: Array[B], start: Int): Unit
def copyToBuffer[B >: A](dest: Buffer[B]): Unit
// Bufferは可変長データの祖型

def ++ [B >: A](that: Iterable[B]): Collection[B]
// いわゆるconcatに等しい
def takeWhile(p: (A) => Boolean): Iterable[A]
// pがfalseとなる最初の要素の前までを返す
def dropWhile(p: (A) => Boolean): Collection[A]
// pがtrueとなる最初の要素以降を返す
def indexOf[B >: A](elem: B): Int
def findIndexOf(p: (A) => Boolean): Int
// pがtrueとなる最初の要素を返す;無しは-1
def sameElements[B >: A](that: Iterable[B]): Boolean

def filter(p: (A) => Boolean): Iterable[A]
// pがtrueとなるすべての要素を返す
def foreach(f: (A) => Unit): Unit
// すべての要素にfを適用する
def map[B](f: (A) => B): Iterable[B]
// すべての要素にfを適用して返す
def flatMap[B](f: (A) => Iterable[B]): Iterable[B]
// 複数のIterableをmapし、それらの結果要素から一つのIterableを生成して返す
// 以上四つは普通strict、すなわち対象要素をすべて評価してから実行される
// ただし遅延クラスではnon-strict、すなわち対象要素を一つずつ評価し実行される

def exists(p: (A) => Boolean): Boolean
// pがtrueとなる要素が在ればtrue
def find(p: (A) => Boolean): Option[A]
// pがtrueとなる最初の要素をSome(要素)として返す;無ければNone
def forall(p: (A) => Boolean): Boolean
// すべての要素でpがtrueならtrue
def partition(p: (A) => Boolean): (Iterable[A], Iterable[A])
// pがtrueとなるすべての要素とfalseとなるすべての要素を別々のIterableで返す

def foldLeft[B](z: B)(op: (B, A) => B): B
// List(1, 2, 3).foldLeft(0) {_ + _} == (((0 + 1) + 2) + 3)
def foldRight[B](z: B)(op: (A, B) => B): B
// List(1, 2, 3).foldRight(0) {_ + _} == (1 + (2 + (0 + 3)))
def /: [B](z: B)(op: (B, A) => B): B
// (0 /: List(1, 2, 3)) {_ + _} == List(1, 2, 3).foldLeft(0) {_ + _}
def :\ [B](z: B)(op: (A, B) => B): B
// (List(1, 2, 3) :\ 0) {_ + _} == List(1, 2, 3).foldRight(0) {_ + _}
def reduceLeft[B >: A](op: (B, A) => B): B
// List(1, 2, 3) reduceLeft {_ + _} == ((1 + 2) + 3)
def reduceRight[B >: A](op: (A, B) => B): B
// List(1, 2, 3) reduceRight {_ + _} == (1 + (2 + 3))


trait Collection[+A] extends Iterable[A]


有限なIterable

abstract def size: Int
def toArray[B >: A]: Array[B]
protected def stringPrefix = thisの単純クラス名
override def toString =
	stringPrefixに続く「(」で接頭され「)」で接尾され「,」を区切り文字とする、全要素の文字列表現


trait Seq[+A] extends PartialFunction[Int, A] with Collection[A]


同一要素型のCollection

abstract def length: Int
def lengthCompare(l: Int): Int
// length - lを返す。このメソッドはワイルドカードで終わるパターン用で、length参照による全体評価を回避するために在る
// 遅延Seqではオーバーライドすること
def reverse: Seq[A]

def take(n: Int): Seq[A]
// 先頭n個の要素を返す
def drop(n: Int): Seq[A]
// 先頭n個を除く残りを返す
def first: A
def firstOption: Option[A]
// Some(最初の要素)またはNoneを返す
def last: A
def lastOption: Option[A]
def lastIndexOf[B >: A](elem: B): Int
// pがtrueとなる最後の要素を返す;無しは-1

def slice(from: Int): Seq[A]
// fromから最終要素までのSeqを返す
def slice(from: Int, until: Int): Seq[A]
// fromからuntilの前までのSeqを返す

def contains(elem: Any): Boolean
// elemを含むならtrue
def containsSlice[B](that: Seq[B]): Boolean
def startsWith[B](that: Seq[B]): Boolean
def endsWith[B](that: Seq[B]): Boolean
def equalsWith[B](that: Seq[B])(f: (A, B) => Boolean): Boolean
// このSeqとthatの同じインデクス要素同士がfでtrueならtrue;長さが異なれば必ずfalse


sealed abstract class List[+A] extends Seq[A]


順序を持つSeq。抽象メンバはクラス「::」とシングルトンNilで実装されている。

def apply(n: Int): A
// n番目の要素を返す(先頭を0番目とする)
def :: [B >:A](x: B): List[B]
// xをこのリストの前に追加;「:」なので右辺が「このリスト」と見なされることに注意
def ::: [B >:A](prefix: List[B]): List[B]
// prefixリストのすべての要素をこのリストの前に追加;「::」だとprefixリスト自体が要素として追加される
abstract def head: A
// 最初の要素を返す
abstract def tail: List[A]
// 最初の要素を除く残りを返す
def init: List[A]
// 最後の要素を除く残りを返す
def dropRight(n: Int): List[A]
// 最後のn個の要素を除く残りを返す
def takeRight(n: Int): List[A]
// 最後のn個の要素から成るリストを返す
def flatten[B](implicit f: (A) => Iterable[B]): List[B]
// List(List(1), List(2), List(3)).flatten[Int] == List(1, 2, 3)
def + [B >:A](x: B): List[B]
// xをこのリストの末尾に追加;「:」では無いので左辺が「このリスト」と見なされる
def - [B >:A](x: B): List[B]
// xを除くリストを返す
def -- [B >:A](that: List[B]): List[B]
// thatリストの要素を除くリストを返す
def remove(p: (A) => Boolean): List[A]
// pがfalseとなる要素から成るリストを返す
def removeDuplicates: List[A]
// 他の要素と「==」な要素を除くリストを返す

def indices: List[Int]
// インデクス番号のリストを返す
def count(p: (A) => Boolean): Int
// pがtrueとなる要素の数を返す
def span(p: (A) => Boolean): (List[A], List[A])
// pがfalseとなる最初の要素の前までと以降とを別々のリストで返す
def break(p: (A) => Boolean): (List[A], List[A])
// pがtrueとなる最初の要素の前までと以降とを別々のリストで返す
def splitAt(n: Int): (List[A], List[A])
// n番目までとそれ以降とを別々のリストで返す
def intersect[B >:A](that: List[B]): List[B]
// このリストとthatリストの両方に存在する要素から成るリストを返す
def union[B >:A](that: List[B]): List[B]
// このリストとthatリストの要素から成る重複の無いリストを返す

def sort(lt: (A, A) => Boolean): List[A]
// 「def lt[A <% Ordered[A]](x: A, y: A) = x < y」となる真偽関数でソートする
// ちなみにOrderedは比較可能を示すトレイト
def reverseMap[B](f: (A) => B): List[B]
// mapしてreverseに等しいが、より最適化された実装を提供する
def reverse_::: [B >:A](prefix: List[B]): List[B]
// 「(prefix.reverse):::このリスト」に等しいが、より最適化された実装を提供する
def zip[B](that: List[B]): List[(A, B)]
// このリストとthatリストの同じインデクス要素同士のタプルから成るリストを返す;結果要素数は短かい方に等しい
def zipAll[B, C >:A, D >:B](that: List[B], thisElem: C, thatElem: D): List[(C, D)]
// 上で、短かい方の残りの各要素は該当Elemであると見なす;結果要素数は長い方に等しい
def zipWithIndex: List[(A, Int)]
// 「(要素, そのインデクス番号)」から成るリストを返す

また、Listシングルトンで以下のメソッドを利用することもできる。

def apply[A](xs: A*): List[A]
// リスト疑似リテラル実体
def unapplySeq[A](x: List[A]): Some[List[A]]
def concat[A](xss: List[A]*): List[A]
// 複数のリストの要素から成るリストを返す
def make[A](n: Int, elem: A): List[A]
// n個のelemから成るリストを返す
def tabulate[A](n: Int, maker: (Int) => A): List[A]
// 上でelemが関数の形;この関数はインデクス番号を実引数とする
def range(start: Int, end: Int): List[Int]
// 「start until end」の結果を要素とするリストを返す
def range(start: Int, end: Int, step: Int): List[Int]
// 「start until end by step」の結果を要素とするリストを返す
def range(start: Int, end: Int, step: (Int) => Int): List[Int]
// 上でstepが関数の形;この関数は逐次増加か減少かいずれか一方のみでなければならない
def fromArray[A](arr: Array[A]): List[A]
def fromArray[A](arr: Array[A], start: Int, len: Int): List[A]
def fromIterator[A](it: Iterator[A]): List[A]
def fromString(str: java.lang.String, separator: Char): List[java.lang.String]

def flatten[A](xss: List[List[A]]): List[A]
def toString(xs: List[Char]): java.lang.String
def exists2[A, B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean
def forall2[A, B](xs: List[A], ys: List[B])(f: (A, B) => Boolean): Boolean
def map2[A, B, C](xs: List[A], ys: List[B])(f: (A, B) => C): List[C]
def map3[A, B, C, D](xs: List[A], ys: List[B], zs: List[C])(f: (A, B, C) => D): List[D]
def mapConserve[A <: AnyRef](xs: List[A])(f: (A) => A): List[A]
// 結果が元と同一なら無変更のxsを返す
def transpose[A](xss: List[List[A]]): List[List[A]]
// 「同じインデクス番号の要素から成るリスト」を要素とするリストを返す(行と列の入れ替えに等しい)
// 元リストの要素リストはすべて同じ長さでなければならない
def unzip[A, B](xs: List[(A, B)]): (List[A], List[B])
def unzip[A, B](xs: Iterable[(A, B)]): (List[A], List[B])

// EitherはOptionに似るが、NoneとSomeに相当するLeftとRightが各々違う型データを保持できる点で異なる
def lefts[A, B](es: Iterable[Either[A, B]]): List[A]
// 各EitherのLeft要素のみから成るリストを返す
def rights[A, B](es: Iterable[Either[A, B]]): List[B]
// 各EitherのRight要素のみから成るリストを返す
def separate[A, B](es: Iterable[Either[A, B]]): (List[A], List[B])
// 各EitherのLeft要素とRight要素とを別々のリストで返す

Option(とEither)

上で出たついでにOptionとEitherも解説しておこう;Eitherは比較的新しいものだが、OptionはML系言語では昔から非常によく使われているものでもあるからだ。


trait Product extends AnyRef


case指定のクラスとシングルトンに暗黙に付加されるトレイト;内部使用用。

abstract def productArity: Int
// コンストラクタ引数の数を返す
abstract def productElement(n: Int): Any
// n番目のコンストラクタ実引数を返す
def productPrefix: java.lang.String
// (普通)コンストラクタ名を返す


sealed abstract class Option[+A] extends Product


インスタンスはSome(値)とNone(これらに特別なメソッドは無いので詳説は略する)だけで、Noneは要するにより型セーフなnullと言えるものだ。このような「コンテナな別型でラップする」テクニックはML系言語で頻繁に使われる。

def orElse[B >: A](alternative: => Option[B]): Option[B]
// 空ならalternative、さもなければ自身を返す
def isDefined: Boolean
// Someならtrue

def elements: Iterator[A]
def filter(p: (A) => Boolean): Option[A]
// 空で無くpがfalseならNone、さもなければ自身を返す
def flatMap[B](f: (A) => Option[B]): Option[B]
// 空ならNoneを返す
def foreach(f: (A) => Unit): Unit
def map[B](f: (A) => B): Option[B]
// 空ならNone、さもなければSome(f(this.get))を返す
// これら四つを持つ、ということは、Optionはfor式で回せる、ということだ
abstract def isEmpty: Boolean
// Noneならtrue
def toList: List[A]

abstract def get: A
// このOptionは空であってはならない
def getOrElse[B >: A](default: => B): B
// 空ならdefault、さもなければ自身の値を返す
def toLeft[X](right: => X): Either[A, X] with Product
// 空ならRightで、さもなければLeftで返す
def toRight[X](left: => X): Either[X, A] with Product
// 空ならLeftで、さもなければRightで返す


sealed abstract class Either[+A, +B] extends AnyRef


抽象メンバは子クラスのLeft(値)及びRight(値)で実装されている;既に述べたように、値の型が一つに限定されるOptionと異なり、LeftとRightの値の型は異なって良い。

def isLeft: Boolean
def isRight: Boolean
def left: LeftProjection[A, B]
def right: RightProjection[A, B]
def swap: Either[B, A] with Product
// LeftならRight、RightならLeftとして返す
def fold[X](fa: (A) => X, fb: (B) => X): X
// Leftならfa(Leftの値)、Rightならfb(Rightの値)を評価する


case final class LeftProjection[+A, +B](val e: Either[A, B]) extends Product


RightProjectionも同様なのでこちらのみ解説する。

def exists(f:(A) => Boolean): Boolean
// Rightならfalse、さもなければf(Leftの値)
def get: A
// Leftの値を返す;RightならNoSuchElementExceptionを投げる
def getOrElse[AA >: A](or: => AA): AA
// Leftの値を返す;Rightならorを返す
def filter[Y](p:(A) => Boolean): Option[Either[A, Y]]
// pがfalseかRightならNone、さもなければLeftを返す
def map[X](f:(A) => X): Either[X, B] with Product
def flatMap[BB >: B, X](f:(A) => Either[X, BB]): Either[X, BB]
def foreach(f:(A) => Unit): Unit
// Rightなら何もしない
def forall(f:(A) => Boolean): Boolean
// Rightならtrue、さもなければf(Leftの値)
def toOption: Option[A]
// RightならNone、LeftならSome(Leftの値)を返す
def toSeq: Seq[A]
// Rightなら空のSeqを返す

また、Eitherシングルトンで以下のメソッドを利用することもできる。

def cond[A, B](test: Boolean, right: => B, left: => A): Either[A, B] with Product
// testがtrueならLeft(left)、さもなければRight(right)を返す
def joinLeft[A, B](es: Either[Either[A, B], B]): Either[A, B]
// es.left.flatMap(x => x)に等しい
def joinRight[A, B](es: Either[A, Either[A, B]]): Either[A, B]
// es.right.flatMap(x => x)に等しい
def merge[T](e: Either[T, T]): T
// LeftであるかRightであるかを問わずその値を返す

Java基本型のScala固有メソッド

scalaパッケージのJava互換各型名クラスで追加されているのは、BooleanとUnitを除くすべてのJava型同士での「to型名」(型名はScalaの大文字で始まるもの)というキャストメソッドだけだ。しかし他にも、ビュー変換によってJava自身のラッパークラスとscala.runtimeの「Rich型名」クラスのメソッド等も暗黙に使えるようになっている。それで、ここではその「Rich型名」の方を解説しておく。


trait Proxy extends AnyRef


Proxyトレイトはselfメソッド宣言を提供する;これは、Anyのpublicでオーバーライド可能なメソッド呼び出しをそのselfをオーバーライドするクラスのそれへと切り替えるものだ。すべての「Rich型名」クラスはこれと次のOrderedを持つ。


trait Ordered[A] extends AnyRef


AnyRef系に比較メソッドを導入するトレイト。compareメソッドはequals及びhashCodeメソッドと矛盾してはならないが、このOrdered自体ではそれは保証されていないことに注意。

def < (that: A): Boolean
def <= (that: A): Boolean
def > (that: A): Boolean
def >= (that: A): Boolean
abstract def compare(that: A): Int
// thatより小さければ負の値、大きければ正の値、等しければ0を返す
def compareTo(that: A): Int
// 上のJava互換なエイリアス

RichBoolean、RichByte及びRichShortは上の抽象メソッドの実装しか持たない。


final class RichInt(start: Int) extends Proxy with Ordered[Int]


RichLongはuntilとtoが無い以外はRichIntと同様である。

def abs: Int
def toBinaryString: java.lang.String
def toHexString: java.lang.String
def toOctalString: java.lang.String
def max(that: Int): Int
def min(that: Int): Int
def until(end: Int): Range
def until(end: Int, step: Int): Range
def to(end: Int): Inclusive


final class RichFloat(x: Float) extends Proxy with Ordered[Float]


RichDoubleも同様なのでこちらのみ解説(と言うか自明なものだけなので紹介)する。

def isInfinity: Boolean
def isNegInfinity: Boolean
def isPosInfinity: Boolean
def abs: Float
def toDegrees: Float
def toRadians: Float
def max(y: Float): Float
def min(y: Float): Float
def ceil: Float
def floor: Float
def round: Int


final class RichChar(x: Char) extends Proxy with Ordered[Char]


asDigit、to及びuntil以外は、java.lang.Characterの同名メソッドがオーバーロードタイプであるための自前実装であろうと思われる。

def isLetter: Boolean
def isDigit: Boolean
def isLetterOrDigit: Boolean
def isLowerCase: Boolean
def isUpperCase: Boolean
def isWhitespace: Boolean
def isControl: Boolean
def toLowerCase: Char
def toUpperCase: Char
def asDigit: Int
def to(y: Char): Iterator[Char]
def until(limit: Char): Iterator[Char]

RichStringとも関連するので、Rangeへと至る継承系も解説しておこう。


trait Projection[+A] extends Iterable[A]


Iterableの遅延相当型。

def force: Iterable[A]
// 相当する非遅延型を返す
override def projection: Projection[A]
// 自身の非抽象インスタンスを返す
def append[B >: A](rest: => Iterable[B]): Projection[B]
// restを追加した自身を返す
// 以下の四つはnon-strict、すなわち各要素は遅延評価される版である
override def filter(p: (A) => Boolean): Projection[A]
override def map[B](f : (A) => B): Projection[B]
override def flatMap[B](f: (A) => Iterable[B]): Projection[B]
override def takeWhile(p: (A) => Boolean): Projection[A]


trait Projection[+A] extends Seq[A] with Iterable.Projection[A]


Seq.Projection;Iterable.Projectionと同様なのでメソッド解説は省略。


trait RandomAccessSeq[+A] extends Seq[A]


final def safeIs(idx: Int, a: Any): Boolean
// idxが可能なインデクスより大きければfalse
def patch[B >: A](from0: Int, patch0: RandomAccessSeq[B], replaced0: Int):
						RandomAccessSeq.Projection[B]
// from0番目からreplaced0個の要素をpatch0で置き換える
// RandomAccessSeq.Projectionも他のProjectionと同様なので特に解説はしない


class Range(val start: Int, val end: Int, val step: Int) extends RandomAccessSeq.Projection[Int]


Range.Inclusiveはこれ(untilに対応)のto対応版。

lazy val length: Int
def apply(idx: Int): Int
// idx番目の要素を返す
def by(step: Int): Range
// このstepと自前のstart及びendで新たなRangeを生成し返す
def contains(x: Int): Boolean
def inclusive: Inclusive


final class RichString(val self: java.lang.String) extends Proxy with RandomAccessSeq[Char] with Ordered[java.lang.String]


Seq系なのでそちらのメソッドも使えることに注意。

def stripLineEnd: java.lang.String
// 行末の改行文字を削除
def stripMargin: java.lang.String
// 行頭の空白及び制御文字を「|」まで削除(「|」も削除)
def stripMargin(marginChar: Char): java.lang.String
// 行頭の空白及び制御文字をmarginCharまで削除(marginCharも削除)
def * (n: Int): java.lang.String
// n回分の自身を返す
def capitalize: java.lang.String
// 先頭1字を大文字にする
def r: scala.util.matching.Regex
// 複数行文字列を使えばバックスラッシュを重ねずに済む

def linesWithSeparators: Iterator[java.lang.String]
// 改行文字で分割する(各行は改行文字を含む)
def split(separator: Char): Array[java.lang.String]
// separatorで分割する
def split(separators: Array[Char]): Array[java.lang.String]
// separatorsの各文字で分割する
def lines: Iterator[java.lang.String]
// linesWithSeparatorsしたその各行にstripLineEndを適用するに等しい

def toArray: Array[Char]
def toBoolean: Boolean
def toByte: Byte
def toDouble: Double
def toFloat: Float
def toInt: Int
def toLong: Long
def toShort: Short

Regex、すなわち正規表現はscala.util.matchingパッケージで導入されており(scala.util.regexpパッケージは文字列以外のオブジェクトへも正規表現マッチングを可能とするもので、一般で言うところの正規表現に相当するのは対文字列限定なこちらutil.matchingの方)、これはjava.util.regexパッケージを利用しているので、使える正規表現等はそれに準じる。すなわち、マッチフラグは「(?フラグ名)」で正規表現に埋め込むことができ、フラグ名「i」は大小文字区別無し、「d」はUnix行(「.」「^」「$」は「\n」のみを行末文字と見なす)、「m」は複数行(「^」と「$」は行末文字でも機能する)、「s」はドットオール(「.」は行末文字も含む)、「u」はUnicodeで大小文字区別無し、「x」は空白と「#」以降は無視する。また、置き換え文字列では正規表現自身と異なり「\」では無く「$」がグループ(「$0」はマッチ全体)を導出し、「\」は「\$」の場合のみ意味(「$」文字自体ということ)を持つ。


class Regex(regex: java.lang.String, groupNames: java.lang.String*) extends AnyRef


groupNamesは各グループを名前で参照できるようにするための文字列Seq(無くても良い)。

val pattern: java.util.regex.Pattern

def findAllIn(source: java.lang.CharSequence): MatchIterator
def findFirstIn(source: java.lang.CharSequence): Option[java.lang.String]
def findFirstMatchIn(source: java.lang.CharSequence): Option[Match]
def findPrefixMatchOf(source: java.lang.CharSequence): Option[Match]
// 先頭部分がマッチしなければNone
def findPrefixOf(source: java.lang.CharSequence): Option[java.lang.String]
// 先頭部分がマッチしなければNone
def replaceAllIn(target: java.lang.CharSequence,
		replacement: java.lang.String): java.lang.String
def replaceFirstIn(target: java.lang.CharSequence,
		replacement: java.lang.String): java.lang.String
def unapplySeq(target: Any): Option[List[java.lang.String]]
// パターンでの正規表現マッチを可能にする
// 「x @ Regexインスタンス名(y, z)」でxをマッチ全体、yをグループ1、zをグループ2に束縛。
// マッチの制約はタプルに準じる、つまり、部分マッチやグループと引数の数が合わない場合はエラー


trait MatchData extends AnyRef


詳細情報のためのトレイト;抽象メンバはMatch及びMatchIteatorで実装される。

abstract val groupNames: Seq[java.lang.String]
abstract val source: java.lang.CharSequence

def matched: java.lang.String
// マッチした文字列
abstract def groupCount: Int
// 正規表現に含まれるグループの数
def group(i: Int): java.lang.String
// グループiにマッチした文字列;そのグループへのマッチ無しならnullを返す
def group(id: java.lang.String): java.lang.String
// グループ番号の代わりに名前で指定
def subgroups: List[java.lang.String]
// 「(1 to groupCount).toList map group」に等しい

abstract def start(i: Int): Int
// グループiにマッチする部分の先頭位置;そのグループへのマッチ無しなら-1を返す
abstract def start: Int
// start(0)に等しい
abstract def end(i: Int): Int
// グループiにマッチする部分の末尾位置+1;そのグループへのマッチ無しなら-1を返す
abstract def end: Int
// end(0)に等しい
def before(i: Int): java.lang.CharSequence
// グループiより前の文字列
// 現定義ではマッチ無しグループの場合IndexOutOfBoundsExceptionとなることに注意(after(i: Int)も同様)
def before: java.lang.CharSequence
// マッチ部分より前の文字列
def after(i: Int): java.lang.CharSequence
// グループiより後ろの文字列
def after: java.lang.CharSequence
// マッチ部分より後ろの文字列


class Match(val source: java.lang.CharSequence, matcher: java.util.regex.Matcher, val groupNames: Seq[java.lang.String]) extends MatchData


マッチ1回分の情報。

val end: Int
val start: Int

def force: Match
// matcherの変化に追随しないようにする;逆に言えばデフォルトでは追随する、ということ


trait Iterator[+A] extends AnyRef


ScalaではIteratorはどちらかと言えばJava等との互換用の意味合いが強いように思われる。

def ++ [B >: A](that: => Iterator[B]): Iterator[B]
def /: [B](z: B)(op:(B, A) => B): B
def :\ [B](z: B)(op:(A, B) => B): B
def addString(buf: StringBuilder,
		start: java.lang.String,
		sep: java.lang.String,
		end: java.lang.String): StringBuilder
def append[B >: A](that: Iterator[B]): Iterator[B]
def contains(elem: Any): Boolean
def copyToArray[B >: A](xs: Array[B], start: Int): Unit
def copyToBuffer[B >: A](dest: Buffer[B]): Unit
def drop(n: Int): Iterator[A]
def dropWhile(p:(A) => Boolean): Iterator[A]
def exists(p:(A) => Boolean): Boolean
def filter(p:(A) => Boolean): Iterator[A]
def find(p:(A) => Boolean): Option[A]
def flatMap[B](f:(A) => Iterator[B]): Iterator[B]
def foldLeft[B](z: B)(op:(B, A) => B): B
def foldRight[B](z: B)(op:(A, B) => B): B
def forall(p:(A) => Boolean): Boolean
def foreach(f:(A) => Unit): Unit
def map[B](f:(A) => B): Iterator[B]
def mkString(sep: java.lang.String): java.lang.String
def mkString(start: java.lang.String,
		sep: java.lang.String,
		end: java.lang.String): java.lang.String
def reduceLeft[B >: A](op:(B, A) => B): B
def reduceRight[B >: A](op:(A, B) => B): B
def slice(from: Int, until: Int): Iterator[A]
def take(n: Int): Iterator[A]
def takeWhile(p:(A) => Boolean): Iterator[A]
def toList: List[A]
def zip[B](that: Iterator[B]): Iterator[(A, B)]
def zipWithIndex: Iterator[(A, Int)]

abstract def hasNext: Boolean
abstract def next: A
// hasNextがfalseならnextはNoSuchElementExceptionを投げる
def duplicate:(Iterator[A], Iterator[A])
// 結果のIterator同士は互いに同期
def readInto[B >: A](xs: Array[B], start: Int, sz: Int): Unit
// 入出力を考慮して、Itarotorの要素数を有限と見なすcopyToArray
def readInto[B >: A](xs: Array[B], start: Int): Unit
// 上でszを配列の長さとする
def readInto[B >: A](xs: Array[B]): Unit
// 上で開始インデクスを0とする

def buffered: BufferedIterator[A]
// BufferedIteratorは先読み可能なIterator
def counted: CountedIterator[A]
// CountedIteratorは読まれた要素数(先頭は0)を自身に記録するIterator


class MatchIterator(val source: java.lang.CharSequence, val regex: Regex, val groupNames: Seq[java.lang.String]) extends Iterator[java.lang.String] with MatchData


IteratorのRegexな実装クラス。

def matchData: Iterator[Match]

配列型

Scala自体においては既の述べたように配列よりもリストの方がはるかに多用されるのだけれども、Javaとの互換が要請される場面においては配列を直接操作しなければならない場面もあるかもしれない(普通はtoListでリスト化して操作してからtoArrayで元に戻せば良い)。


trait Mutable[A] extends RandomAccessSeq[A]


RandomAccessSeqにupdateメソッドを追加。

def readOnly: RandomAccessSeq[A]
// lengthとapplyメソッドが追加されたRandomAccessSeqを返す;クラス名は「元クラス名RO」になる
abstract def update(idx: Int, what: A): Unit
// 最初の要素のインデクス(idx)は0


trait ArrayLike[A] extends Mutable[A]


Arrayを結果するforceのみを強制。

abstract def force: Array[A]


trait Projection[A] extends RandomAccessSeq.MutableProjection[A] with ArrayLike[A]


Array.Projection。MutableProjectionはRandomAccessSeq.Projectionと同様なので解説は省略。

protected abstract def newArray[B >: A](length: Int, elements: Iterator[A]): Array[B]


trait Array0[A] extends ArrayLike[A]


継承メソッドの返すProjectionを上のArray.Projectionへと切り替える。


final class Array[A](_length: Int) extends Array0[A]


def this(dim1: Int, dim2: Int): Array[A]
// 多次元配列用コンストラクタ(この他、3次元〜9次元用まで在る)
// 使い方は既に触れたように「new Array[Array[Int]](3, 3)」等とかなり面倒

def apply(i: Int): A
def length: Int
def indices: Array[Int]
def zip[B](that: Array[B]): Array[(A, B)]
def zipWithIndex: Array[(A, Int)]

def deepEquals(that: Any): Boolean
def deepMkString(start: java.lang.String,
		sep: java.lang.String,
		end: java.lang.String): java.lang.String
def deepMkString(sep: java.lang.String): java.lang.String
def deepToString: java.lang.String

また、Arrayシングルトンで以下のメソッドを利用することもできる。

// Array疑似リテラルの実体
def apply(xs: Boolean*): Array[Boolean]
def apply(xs: Byte*): Array[Byte]
def apply(xs: Char*): Array[Char]
def apply(xs: Short*): Array[Short]
def apply(xs: Int*): Array[Int]
def apply(xs: Long*): Array[Long]
def apply(xs: Float*): Array[Float]
def apply(xs: Double*): Array[Double]
def apply(xs: Unit*): Array[Unit]
def apply[A <: AnyRef](xs: A*): Array[A]
def unapplySeq[A](x: Array[A]): Option[Seq[A]]

def copy(src: AnyRef, srcPos: Int,
		dest: AnyRef, destPos: Int, length: Int): Unit
// java.lang.System.arraycopyは多相等を考慮していないのでScalaではこちらを使うこと
def concat[T](xs: Seq[T]*): Array[T]

def make[A](n: Int, elem: A): Array[A]
// elmで初期化された要素n個の配列を返す
def range(start: Int, end: Int): Array[Int]
// 「start until end」の各値を要素とする配列を返す
def fromFunction[A](f:(Int) => A)(n: Int): Array[A]
// fへの実引数は生成される配列のインデクス
def fromFunction[A](f:(Int, Int) => A)(n1: Int, n2: Int): Array[Array[A]]
// 以下同様に5次元まで用意されている

マップ型

scala.Predefで導入されているマップすなわち連想配列の実体はscala.collection.immutable.HashMapである。


trait scala.collection.Map[A, +B] extends PartialFunction[A, B] with Collection[(A, B)]


すべてのマップ型が持つべきメソッド群。

def apply(key: A): B
// インデクスの代わりにキー指定で値を取り出せる
abstract def get(key: A): Option[B]
// applyに準じるがOptionでくるんで返す
def getOrElse[B2 >: B](key: A, default: => B2): B2
// applyに準じるが値無しはdefaultを返す
def contains(key: A): Boolean
// キーに対応する値が在ればtrue
def isDefinedAt(key: A): Boolean
// containsと同じ
def default(key: A): B
// キーに対応する値が無い場合はデフォルト値を返す
// オーバーライド用でこのトレイトではNoSuchElementExceptionを投げるだけ

abstract def size: Int
def keySet: Set[A]
// すべてのキーから成るセットを返す
def keys: Iterator[A]
// すべてのキーから成るIteratorを返す
def values: Iterator[B]
// すべての値から成るIteratorを返す

def filterKeys(p:(A) => Boolean): Projection[A, B]
// キーへのfilter;値の評価はされない
def mapElements[C](f:(B) => C): Projection[A, C]
// 値へのmap;キーの評価はされない


trait scala.collection.immutable.Map[A, +B] extends scala.collection.Map[A, B]


不変(immutable)なので、文字列やリストと同様に操作はすべて新たなマップのインスタンスを返す。

def + [B1 >: B](kv:(A, B1)): Map[A, B1]
def + [B1 >: B](kv1:(A, B1), kv2:(A, B1), kvs:(A, B1)*): Map[A, B1]
def ++ [B1 >: B](kvs: Iterable[(A, B1)]): Map[A, B1]
def ++ [B1 >: B](kvs: Iterator[(A, B1)]): Map[A, B1]
abstract def - (key: A): Map[A, B]
def - (key1: A, key2: A, keys: A*): Map[A, B]
def -- (keys: Iterable[A]): Map[A, B]
def -- (keys: Iterator[A]): Map[A, B]

abstract def empty[C]: Map[A, C]
// 同じキー型・値型の空のマップを返す
def transform[C](f:(A, B) => C): Map[A, C]
def withDefault[B1 >: B](d:(A) => B1): Map[A, B1]
// dでdefaultメソッドを実装したマップを返す
def withDefaultValue[B1 >: B](d: B1): Map[A, B1]
// 「withDefault(x => d)」に等しい

以下scala.collection.immutable.HashMapまでのそれをも含むクラス階層はすべてHashMapの実装実体であり、マップ型をただ使うだけなら理解する必要はまったく無いので省略する。なお、(scala.collection.immutable.)Mapシングルトンで以下のメソッドを利用することもできる。

def apply[A, B](elems: (A, B)*): Map[A, B]
// 疑似リテラル実体
def empty[A, B]: Map[A, B]
// その型の空マップを返す

セット型

scala.Predefで導入されているセットすなわち無重複リストの実体はscala.collection.immutable.HashSetである。


trait scala.collection.Set[A] extends (A) => Boolean with Collection[A]


def apply(elem: A): Boolean
// containsに等しい;これは他の集合型のapplyの動作と直感的にズレるので注意
abstract def contains(elem: A): Boolean
def ** (that: Set[A]): Set[A]
// 自身とthatとで値が同じ要素のみ返す
def subsetOf(that: Set[A]): Boolean
// 自身がthatのサブセットならtrue


trait scala.collection.immutable.Set[A] extends scala.collection.Set[A]


abstract def + (elem: A): Set[A]
def + (elem1: A, elem2: A, elems: A*): Set[A]
def ++ (elems: Iterable[A]): Set[A]
def ++ (elems: Iterator[A]): Set[A]
abstract def - (elem: A): Set[A]
def - (elem1: A, elem2: A, elems: A*): Set[A]
def -- (elems: Iterable[A]): Set[A]
def -- (elems: Iterator[A]): Set[A]

abstract def empty[B]: Set[B]
// 同じ要素型の空のセットを返す
def intersect(that: Set[A]): Set[A]
// 「**」に等しい


trait scala.collection.mutable.FlatHashTable[A] extends AnyRef


scala.collection.immutable.HashSetはその名が示す通りハッシュテーブルを使って実装されており、すなわちこのトレイトがその実装の中身である。

protected var table: Array[AnyRef]
protected var tableSize: Int
protected var threshold: Int

protected final def loadFactorDenum: Int
protected final def improve(hcode: Int): Int
protected final def index(hcode: Int): Int
protected def clear: Unit
protected def elemHashCode(elem: A): Int
protected def initialSize: Int
protected def loadFactor: Int

def containsEntry(elem: A): Boolean
// セット型では「contains」かさらには「apply」(「インスタンス名(elem)」の形)の方が簡便
def addEntry(elem: A): Boolean
// セット型では「+」の方が簡便
def removeEntry(elem: A): Option[A]
// セット型では「-」の方が簡便
def size: Int
def findEntry(elem: A): Option[A]
def elements: Iterator[A]

scala.collection.immutable.HashSet自体はHashSetの(さらなる)実装実体であり、セット型をただ使うだけなら理解する必要はまったく無いので省略する。なお、(scala.collection.immutable.)Setシングルトンで以下のメソッドを利用することもできる。

def apply[A](elems: A*): Set[A]
// 疑似リテラル実体
def empty[A]: Set[A]
// その型の空セットを返す

XML型

XMLリテラルの型はscala.xml.Node(の子型であるscala.xml.Elem、scala.xml.Group、scala.xml.SpecialNodeのいずれか)であり、ちょっとしたXMLデータの操作等ならたいていはそれ(周り)だけ知っていれば事足りるものと思う。なお、以下でscalaパッケージに無いパッケージ無指定なクラス・トレイト・シングルトンはscala.xmlパッケージのものである。


@serializable class NamespaceBinding(val prefix: java.lang.String, val uri: java.lang.String, val parent: NamespaceBinding) extends AnyRef


接頭辞(prefix)を名前空間URIに束縛する。

def getPrefix(_uri: java.lang.String): java.lang.String
def getURI(_prefix: java.lang.String): java.lang.String
def toString(sb: StringBuilder, stop: NamespaceBinding): Unit
// 自身がstopで無ければ必要な「xmlns = 名前空間URI」を追加の上sbに書き込む
def toString(stop: NamespaceBinding): java.lang.String
// toString(暗黙のsb, stop)に等しい
override def toString: java.lang.String
// toString(TopScope)に等しい
// scala.xml.TopScopeは「xmlns:xml = "http://www.w3.org/XML/1998/namespace"」で
// あるNameSpaceBindingの子ケースシングルトン


abstract class NodeSeq extends Seq[Node]


XPath的演算子を導入。

abstract def theSeq: Seq[Node]
// 本体

def \ (that: java.lang.String): NodeSeq
// 「\ "タグ名"」でそのタグ名な子すべてを返す
// 「\ "_"」ですべての子を返す
// 「\ "@属性名"」でその属性の値を(Group型で)返す
// 「\ "@{名前空間URI}属性名"」でその名前空間URIに属する属性の値を返す
// 接頭辞リテラルでの属性名指定はサポートしていない
def \\ (that: java.lang.String): NodeSeq
// 子の代わりに子孫指定となる他は「\」に準じる
def apply(f:(Node) => Boolean): NodeSeq
def apply(i: Int): Node
override def equals(x: Any): Boolean
// 値一致ならtrue
def text: java.lang.String
// 内容文字列を返す

NodeSeqシングルトンから以下のものも利用可能である。

final val Empty: NodeSeq

def fromSeq(s: Seq[Node]): NodeSeq
// 「theSeq = s」なNodeSeqを返す
implicit def view(s: Seq[Node]): NodeSeq
// ビュー変換用


@serializable abstract class MetaData extends Collection[MetaData]


属性の集合;実体はUnprefixedAttribute、PrefixedAttribute、Nullのいずれか。

abstract def key: java.lang.String
// 属性名を返す;複数ある場合はnext.keyで次の属性名を参照可
abstract def value: Seq[Node]
// 属性値(の集合?)を返す
def length: Int
def length(i: Int): Int
// 「length + i」を返す;privateの付け忘れかもしれない
abstract def getNamespace(owner: Node): java.lang.String
// ownerがこのMetadataの要素ならその名前空間名を返す

abstract def apply(key: java.lang.String): Seq[Node]
// 接頭辞無し属性の値を返す;無しはnull
abstract def apply(namespace_uri: java.lang.String,
		scp: NamespaceBinding,
		k: java.lang.String): Seq[Node]
// 接頭辞付き属性の値を返す(kが属性名);無しはnull
final def apply(namespace_uri: java.lang.String,
		owner: Node,
		key: java.lang.String): Seq[Node]
// apply(namespace_uri, owner.scope, key)に等しい
final def get(key: java.lang.String): Option[Seq[Node]]
// applyと同様だが結果はOption型
final def get(uri: java.lang.String,
		scope: NamespaceBinding,
		key: java.lang.String): Option[Seq[Node]]
final def get(uri: java.lang.String,
		owner: Node,
		key: java.lang.String): Option[Seq[Node]]
abstract def remove(key: java.lang.String): MetaData
abstract def remove(namespace: java.lang.String,
		scope: NamespaceBinding,
		key: java.lang.String): MetaData
final def remove(namespace: java.lang.String,
		owner: Node,
		key: java.lang.String): MetaData
def append(updates: MetaData, scope: NamespaceBinding): MetaData
// 属性が重なる場合はupdatesの方が選択される
def append(updates: MetaData): MetaData
// append(updates, TopScope)に等しい

override def equals(that: Any): Boolean
// deep(参照先の要素も比較)なequals
abstract def equals1(that: MetaData): Boolean
// shallow(参照先が等しければその要素は無視)なequals
abstract def isPrefixed: Boolean
abstract def wellformed(scope: NamespaceBinding): Boolean
def hasNext: Boolean
abstract def next: MetaData
// 次の要素以降を返す;無しはNull
abstract def copy(next: MetaData): MetaData
// nextを次の要素とするMetaDataを返す
def containedIn1(m: MetaData): Boolean
// 「m.equals1(this) || containedIn1(m.next)」に等しい
abstract def toString1(sb: StringBuilder): Unit
// 最初の要素を文字列化
def toString1: java.lang.String
// toString(暗黙のsb)に等しい
def toString(sb: StringBuilder): StringBuilder
// 全要素を文字列化


class UnprefixedAttribute(val key: java.lang.String, val value: Seq[Node], next1: MetaData) extends MetaData


接頭辞無しな属性。

def this(key: java.lang.String,
		value: Option[Seq[Node]],
		next: MetaData): UnprefixedAttribute
// UnprefixedAttribute(key, value.get, next)に等しい
def this(key: java.lang.String,
		value: java.lang.String,
		next: MetaData): UnprefixedAttribute
// UnprefixedAttribute(key, Text(value), next)に等しい;Textについては後述


class PrefixedAttribute(val pre: java.lang.String, val key: java.lang.String, val value: Seq[Node], val next: MetaData) extends MetaData


接頭辞付き属性。

def this(pre: java.lang.String,
		key: java.lang.String,
		value: java.lang.String,
		next: MetaData): PrefixedAttribute
// PrefixedAttribute(key, Utility.parseAttributeValue(value), next)に等しい
// Utilityについては後述

Nullには独自メソッドは無いので解説は省略する。


abstract class Node extends NodeSeq


実体は既に書いたようにElem、Group、SpecialNode(これもさらに子が実体だが)のいずれかである。

abstract def label: java.lang.String
// タグ名を返す
abstract def child: Seq[Node]
// このノードのすべての子を返す
def descendant: List[Node]
// このノードのすべての子孫を返す
def descendant_or_self: List[Node]
// このノードの自身を含むすべての子孫を返す
def attributes: MetaData
// 順不同の全属性より成るMetaDataを返す
final def attribute(key: java.lang.String): Option[Seq[Node]]
// attributes.getValue(key)に等しい
final def attribute(uri: java.lang.String, key: java.lang.String): Option[Seq[Node]]
// attributes.getValue(uri, this, key)に等しい
def toString(stripComment: Boolean): java.lang.String
override def toString: java.lang.String
// toString(false)に等しい

def prefix: java.lang.String
// 接頭辞を返す
def scope: NamespaceBinding
def getNamespace(pre: java.lang.String): java.lang.String
// scope.getURI(pre)に等しい;ただしscopeがnullならnullを返す
def namespace: java.lang.String
// getNamespace(this.prefix)に等しい
def nameToString(sb: StringBuilder): StringBuilder
// 接頭辞付きタグ名を返す
def xmlType: TypeSymbol
// スキーマの種類を返す;デフォルトはnull

Nodeシングルトンで以下のメソッド等を利用することもできる。

val EmptyNamespace: java.lang.String

final def NoAttributes: MetaData
// 空のMetaData
def unapplySeq(n: Node): Some[(java.lang.String, MetaData, Seq[Node])]


@serializable class Elem(val override prefix: java.lang.String, val label: java.lang.String, val override attributes: MetaData, val override scope: NamespaceBinding, val child: Node*) extends Node


特殊なもので無ければXMLリテラル(と互換なもの)は普通この型になる。

final def % (updates: MetaData): Elem
// updatesをMetaData.appendしたElemを返す

Elemシングルトン

def apply(prefix: java.lang.String,
		label: java.lang.String,
		attributes: MetaData,
		scope: NamespaceBinding,
		child: Node*): Elem
// 一応シングルトン版applyがあるので疑似リテラルも作れるわけだが、ただのXMLリテラルの方が簡便と思う
def unapplySeq(n: Node): Option[(java.lang.String,
			java.lang.String,
			MetaData,
			NamespaceBinding,
			Seq[Node])]


case class Group(val nodes: Seq[Node]) extends Node with Product


複数のNodeを一つに見せかけるためのややトリッキーなクラス。メソッドは親のオーバーライドだけなので省略(以下同様)。


abstract class SpecialNode extends Node with scala.xml.pull.XMLEvent


特殊なもの;XMLEventは、Pullパーサ(イベント駆動なSAXパーサに似るが、イベントの要求や会得はSAXと異なりパーサ側で無くユーザ側で行うパーサ)向けのマーカートレイトに過ぎないので解説は省略する(要するにSpecialNode系はPullパーサではイベントとなるということである)。


case class Comment(val commentText: java.lang.String) extends SpecialNode with Product


XMLコメント。


case class EntityRef(val entityName: java.lang.String) extends SpecialNode with Product


実体参照。


case class ProcInstr(val target: java.lang.String, val proctext: java.lang.String) extends SpecialNode with Product


XML処理命令。


@serializable class Atom[+A](val data: A) extends SpecialNode


いわゆる#PCDATAなものはすべてこの系に属する。

def label: java.lang.String = "#PCDATA"


case class Text(val _data: java.lang.String) extends Atom[java.lang.String] with Product


特殊なもので無ければこの型になる。


case class PCData(val _data: java.lang.String) extends Atom[java.lang.String] with Product


XHTMLでCDATAなものをXMLのPCDATAとして扱うためのクラス。


case class Unparsed(val _data: java.lang.String) extends Atom[java.lang.String] with Product


解析不能なもの;未解析で保持されそのまま出力される。


trait scala.xml.parsing.TokenTests extends AnyRef


Utilityシングルトンの親。XMLを部分的にパースするためのヘルパートレイトである。

def isPubIDChar(ch: Char): Boolean
// 公開識別子に使える字ならtrue
// XHTMLでは例えば"-//W3C//DTD HTML4.0 Transitional//EN"が公開識別子
def checkPubID(s: java.lang.String): Boolean
// 公開識別子として妥当ならtrue
def checkSysID(s: java.lang.String): Boolean
// システム識別子として妥当ならtrue
// XHTMLでは例えば"http://www.w3.org/TR/REC-html40/loose.dtd"がシステム識別子
final def isSpace(ch: Char): Boolean
// XMLの空白文字ならtrue
final def isSpace(cs: Seq[Char]): Boolean
// XMLの空白文字の連なりならtrue
def isNameChar(ch: Char): Boolean
// XMLで名前に使用可能な字ならtrue
def isNameStart(ch: Char): Boolean
// XMLで名前先頭文字として使用可能ならtrue
def isName(s: java.lang.String): Boolean
// XMLで名前として使用可能ならtrue
def isValidIANAEncoding(ianaEncoding: Seq[Char]): Boolean
// IANAエンコーディング名に等しい文字列ならtrue;デコーダの有無は確認しない

XMLシングルトンで以下のメソッド等を利用することもできる。

val xml: java.lang.String = "xml"
val xmlns: java.lang.String = "xmlns"
val lang: java.lang.String = "lang"
val preserve: java.lang.String = "preserve"
val space: java.lang.String = "space"
val namespace: java.lang.String = "http://www.w3.org/XML/1998/namespace"
val encoding: java.lang.String = "ISO-8859-1"
// ISO-8859-1はLatin-1(英語を含む西ヨーロッパ諸文字)のこと

// loadFile及びloadはJavaのXMLパーサを利用している
final def loadFile(fileName: java.lang.String): Elem
final def loadFile(file: java.io.File): Elem
final def loadFile(fileDesc: java.io.FileDescriptor): Elem

final def load(is: java.io.InputStream): Elem
final def load(reader: java.io.Reader): Elem
final def load(sysID: java.lang.String): Elem
final def load(source: org.xml.sax.InputSource): Elem

final def loadString(string: java.lang.String): Elem
// stringをXMLデータ自体と見なしてElemに変換

// saveはXML宣言とDOCTYPE宣言は書き込まない
final def save(filename: java.lang.String,
		node: Node,
		enc: java.lang.String): Unit
final def save(filename: java.lang.String, node: Node): Unit
// デフォルトのエンコーディング(ISO-8859-1)でのsave呼び出し

final def write(w: java.io.Writer,
		node: Node,
		enc: java.lang.String,
		xmlDecl: Boolean,
		doctype: DocType): Unit
// xmlDeclはfalse、doctypeはnullでも良い;Writerのcloseはユーザ側ですること
final def saveFull(filename: java.lang.String,
		node: Node,
		enc: java.lang.String,
		xmlDecl: Boolean,
		doctype: DocType): Unit
// 実体はwriteの呼び出しだがファイルのopenとcloseはこのメソッド自体が行う
final def saveFull(filename: java.lang.String,
		node: Node,
		xmlDecl: Boolean,
		doctype: DocType): Unit
// デフォルトのエンコーディング(ISO-8859-1)でのsaveFull呼び出し

Utilityシングルトンで以下のメソッド等を利用することもできる。

def appendEscapedQuoted(s: java.lang.String,
		sb: StringBuilder): StringBuilder
// sを二重引用符で囲み、s内の二重引用符はエスケープしたものをsbに追加して返す
def appendQuoted(s: java.lang.String, sb: StringBuilder): StringBuilder
// s内に二重引用符が在れば一重引用符、無ければ二重引用符で囲んだsをsbに追加して返す
def checkAttributeValue(value: java.lang.String): java.lang.String
// valueが属性値に可能な文字のみで構成されていればnull、さもなければ適切なエラーメッセージを返す
def collectNamespaces(n: Node, set: Set[java.lang.String]): Unit
// n内の名前空間をsetに集める
def collectNamespaces(nodes: Seq[Node]): Set[java.lang.String]
// nodes内の名前空間(子孫及び空のも含む)を集めたものを返す
final def escape(text: java.lang.String): java.lang.String
// 「<」、「>」、「&」、「"」、「’」(IE用)を文字参照に変換して返す
final def escape(text: java.lang.String, s: StringBuilder): StringBuilder
// sにescape済みtextを追加する
final def unescape(ref: java.lang.String, s: StringBuilder): StringBuilder
// refのescapeを解除してsに追加する
def getName(s: java.lang.String, index: Int): java.lang.String
// XMLの名前な部分を返す
def hashCode(pre: java.lang.String,
		label: java.lang.String,
		attribHashCode: Int,
		scpeHash: Int,
		children: Seq[Node]): Int
// 該当する要素のハッシュコードを返す
def parseAttributeValue(value: java.lang.String): Seq[Node]
// 属性値文字列を実値に変換してSeq[Node]にまとめ返す
def parseCharRef(ch: () => Char,
		nextch: () => Unit,
		reportSyntaxError: (java.lang.String) => Unit): java.lang.String
// 文字参照をUTF-8な実体に変換

final def prefix(name: java.lang.String): Option[java.lang.String]
// その被修飾名の接頭辞を返す
def publicLiteralToString(sb: StringBuilder,
		s: java.lang.String): StringBuilder
def publicLiteralToString(s: java.lang.String): java.lang.String
def sequenceToXML(children: Seq[Node],
		pscope: NamespaceBinding,
		sb: StringBuilder,
		stripComment: Boolean): Unit
def systemLiteralToString(sb: StringBuilder,
		s: java.lang.String): StringBuilder
def systemLiteralToString(s: java.lang.String): java.lang.String
def toXML(n: Node, stripComment: Boolean): java.lang.String
// nの文字列表現を返す
def toXML(x: Node,
		pscope: NamespaceBinding,
		sb: StringBuilder,
		stripComment: Boolean): Unit
// sbにxのツリー表現をpscopeの名前空間で追加する
def toXML(n: Node): java.lang.String
// コメントを削除したnの文字列表現を返す
def trimProper(x: Node): Seq[Node]
// xの子要素を重複なしにする。属性とテキストノードでないAtomノードには影響なし
def trim(x: Node): Node
// もっぱらtrimProper内部使用用。xはテキストノードであってはならない

def sort(md: MetaData): MetaData
// mdをソートして返す
def sort(n: Node): Node
// その属性(接頭辞は無視される)群がソートされたnを返す

前ページ | トップページ | 次ページ