Predefに定義された関数は、すべてのScalaのソースにおいて自動でimportされている。そのため、Predef.method()のようにクラス名を指定しなくても、method()のみで実行可能。
printやprintlnはPredefで定義されている。JavaのようにSystem.out.printlnという長い記述をしなくても、printlnのみで標準出力ができるのは、これのお陰。
scalaパッケージの直下にいないMapやSetなどのクラスがimportしなくても利用できるのも、Predefの中でvalとして呼び出されているお陰。
また、暗黙の型変換に関する定義も行われている。これらの記述は普段Scalaを利用する上で可能な記述を影から支えている。
PredefのScaladoc
http://www.scala-lang.org/api/current/scala/Predef$.html
長くなったので、Predefの中で設定されてるimplicitな記述については別途
scala.Predefの暗黙の型変換
java.lang.System.exitを呼び出す。つまりJVMを終了する。REPLでexitと入力すると終了するのは、これを呼び出しているから(通常の終わり方は、:q)。
// 指定したステータスコードでJVMを終了する
exit(1)
// ステータスコードを省略した場合は0で終了
exit()
RuntimeExceptionをthrowする。
error("nemui")
//=> java.lang.RuntimeException: nemui
テストなどで用いられる、あのassert。評価(Boolean)を渡して、結果が間違っていればjava.lang.AssertionErrorをthrowする。
// 間違った評価を渡すとErrorが起きる
assert(10 == 3)
//=> java.lang.AssertionError: assertion failed
// 引数にメッセージを付けることもできる
assert(10 == 5, "baka")
//=> java.lang.AssertionError: assertion failed: baka
尚、コンパイラのオプションで「-Xelide-below」をscala.annotation.elidableの「ASSERTION」(2000)よりも大きい値に設定すると、assertは無視される。
// REPLで引数付けて立ち上げ
scala -Xelide-below 2001
scala> assert(2 == 3)
//=> エラーが起きない
処理内容自体はassertとまったく同じ。assumeは処理の前提条件のチェックに、assertは処理結果のチェックに使う、くらいの気持ちで使ってる。
scala.Predef内のコメントでは、assertは「a predicate which needs to be proven」、assumeは「an axiom for a static checker」を表現するものとしている。
assume(1 == 2)
//=> java.lang.AssertionError: assumption failed
assume(1 + 1 == 3, "baka")
//=> java.lang.AssertionError: assumption failed: baka
assertやassumeと同じくテスト用関数。ErrorではなくIllegalArgumentExceptionを返す。
関数の利用者に対して「おまえの使い方、間違ってるよ」と主張したい場合などに使う。
require(2 == 4)
//=> java.lang.IllegalArgumentException: requirement failed
require(2 == 4, "uso")
//=> java.lang.IllegalArgumentException: requirement failed: uso
ensuringはassertのように括弧内に条件を書くのではなく、後置で条件を書ける。尚、ensuringは呼び出されると評価をそのままassertに投げるので、エラー内容はassertと同一になる。
10 ensuring( _ < 10 )
//=> java.lang.AssertionError: assertion failed
これは暗黙の型変換でAny型にensuring関数を追加することで行っている。ので、Scalaの型はすべてensuringが付加されているものと考えて良い。
// Predef内で下記のように、AnyがEnsuringに変換可能とされている
implicit def any2Ensuring[A](x: A): Ensuring[A] = new Ensuring(x)
たとえば下記のように関数の結果に対してテストを行うこともできる。戻り値が返ってきたところでassertで比較するよりもスマート。
def sum(i : Int, j : Int) = { i + j } ensuring (_ < 10, "dame")
sum(10, 20)
//=> Exception in thread "main" java.lang.AssertionError: assertion failed: dame
改行なしで標準出力する。Console.printを呼び出し、そこからSystem.out.printを呼び出している。
print("hello")
//=> hello
末尾に改行を付けて標準出力する。Console.printlnを呼び出し、そこからSystem.out.printlnを呼び出している。
println("hello")
//=> hello
みんな大好き、printf。java.lang.Stringのformatで整形した後、Console.printが呼び出される。ので、末尾に改行は付かない。
printf("%d月%d日 %s", 5, 3, "晴れ" )
//=> 5月3日 晴れ
printfの整形部分。java.lang.Stringのformatを呼び出している。
format("%d/%d/%d", 2011, 5, 3)
//=> 2011/5/3
標準入力(java.lang.System.in)から1行読み込む。内部的には、new BufferedReader(new InputStreamReader(java.lang.System.in))を利用している。
scala> val in = readLine()
input
scala> in
res0: String = input
引数を指定すると、下記のように標準出力付きで実行される。
scala> val in = readLine("input your name => ")
input your name =>name
scala> in
res0: String = name
コマンドラインからインストールとかをやっていると良く聞かれる、OKなら「y」、OKじゃなければ「N」を入力しろ的なアレ。
scala> val in = readBoolean()
Y
in: Boolean = true
scala> val in = readBoolean()
N
in: Boolean = false
大文字小文字関係なく、true、t、yes、yが入力されるとtrue、それ以外だとfalse。空文字もfalseなので注意。
型を指定して読み込める。
scala> val in = readInt()
100
in: Int = 100
// 型に沿わないものを入れるとエラー
scala> val in = readInt()
hoge
java.lang.NumberFormatException: For input string: "hoge"
// 溢れるものを入れてもエラー
scala> val in = readByte()
256
java.lang.NumberFormatException: Value out of range. Value:"256" Radix:10
readfはjava.text.MessageFormatを使って形式に沿って分解した結果を、List[Any]で返す。
scala> readf("{0,number}/{1,number}")
2011/05
res0: List[Any] = List(2011, 5)
readf1〜readf3は、readfした結果から、それぞれ前方1つ、前方2つ、前方3つの値を返す。型はAny、Tuple2、Tuple3。
scala> readf1("{0}/{1}/{2} {3}:{4}")
2011/05/03 13:02
res0: Any = 2011
scala> readf1("{0}/{1}/{2} {3}:{4}")
2011/05/03 13:02
res1: (Any, Any) = 2011
scala> readf1("{0}/{1}/{2} {3}:{4}")
2011/05/03 13:02
res2: (Any, Any, Any) = (2011,05,03)
java.lang.Thread.currentThread()と等価。
currentThread
//=> java.lang.Thread = Thread[main,5,main]
指定したクラスのjava.lang.Class型のインスタンスを取得する。
classOf[String]
//=> java.lang.Class[String] = class java.lang.String