この投稿はScala Advent Calendar 2013の4日目の記事です。
最近Scala勉強会 in 東京 #rpscalaで初心者向けセッションのコーナーが始めたみたいです。それに便乗して自分も初心者向けの記事というかscala習い始めにすごいなと思ったREPLの機能を何個か書いてみたいと思います。
scala> val a = 1 + 2
a: Int = 3
と変数aに入力したものを
scala> println(a)
3
として使えるのは当然ですが、単に
scala> 1 + 2
res1: Int = 3
と式だけ書いた場合はresXという変数に代入されます。
scala> println(res1)
3
Xの部分は、res1、res2、res3とインクリメントされていきます。
REPLというと1行ずつ入力していくようなイメージがあるかと思いますが、まとめて入力することも出来ます。
まずREPL上で「:paste」と打ってみて下さい。pasteモードに入ります。
scala> :paste
// Entering paste mode (ctrl-D to finish)
ここで複数行に渡る式を書いて
(1 to 10).toList.foreach {
println _
}
ctrl-Dを押す。すると、複数行で書いたものがまとめてコンパイルされます。
この書き方だとコンパニオンオブジェクトも使えたはず。
どこかに書いたソースコードをコピペしてREPLに貼る、なんてときによく使えます。
2.11でREPLのコマンドいろいろ追加されそうなのに今気づいた。
REPLの話題からそれますが。
REPLでもタブ補完があります。例えばString.でタブを押すとStringクラスのメソッド名の一覧がでます。
scala> "ABC". [TAB]
+ asInstanceOf charAt codePointAt codePointBefore
codePointCount compareTo compareToIgnoreCase concat contains
contentEquals endsWith equalsIgnoreCase getBytes getChars
indexOf intern isEmpty isInstanceOf lastIndexOf
length matches offsetByCodePoints regionMatches replace
replaceAll replaceFirst split startsWith subSequence
substring toCharArray toLowerCase toString toUpperCase
trim
ところがこの一覧に存在しないメソッドが使えたりします。
scala> "ABC".min
res16: Char = A
Stringクラスに存在しないメソッドを呼んでるのにコンパイルエラーにならない。
何故なんでしょうねー。
ってところで裏で働いてるのが「暗黙の型変換(implicit conversions)」です。
具体的にはPredefの中のこいつ。StringからStringOptへの暗黙の型変換です。
"ABC"はStringクラスのインスタンスなのでminなんてメソッドが使えないのですが、あらかじめ暗黙の型変換が宣言されていれば、"ABC"をStringOptへ変換してからメソッドを呼ぶことができます。minはStringOptクラスのメソッドです。
REPLでStringOptのメソッドを確認。
scala> new scala.collection.immutable.StringOps("ABC")
res17: scala.collection.immutable.StringOps = ABC
scala> res17.
* ++ ++: +: /:
/:\ :+ :\ > >=
addString aggregate apply asInstanceOf canEqual
capitalize collect collectFirst combinations compare
compareTo contains containsSlice copyToArray copyToBuffer
corresponds count diff distinct drop
dropRight dropWhile endsWith exists filter
filterNot find flatMap fold foldLeft
foldRight forall foreach format formatLocal
groupBy grouped hasDefiniteSize head headOption
indexOf indexOfSlice indexWhere indices init
inits intersect isDefinedAt isEmpty isInstanceOf
isTraversableAgain iterator last lastIndexOf lastIndexOfSlice
lastIndexWhere lastOption length lengthCompare lines
linesIterator linesWithSeparators map max maxBy
min minBy mkString nonEmpty padTo
par partition patch permutations prefixLength
product r reduce reduceLeft reduceLeftOption
reduceOption reduceRight reduceRightOption replaceAllLiterally repr
reverse reverseIterator reverseMap sameElements scan
scanLeft scanRight segmentLength seq size
slice sliding sortBy sortWith sorted
span split splitAt startsWith stringPrefix
stripLineEnd stripMargin stripPrefix stripSuffix sum
tail tails take takeRight takeWhile
to toArray toBoolean toBuffer toByte
toDouble toFloat toIndexedSeq toInt toIterable
toIterator toList toLong toMap toSeq
toSet toShort toStream toString toTraversable
toVector union updated view withFilter
zip zipAll zipWithIndex
それにしても知らないメソッド結構多いなー。
sbtやplayを使ってる人は「sbt console」とか「play console」て打つとREPLが立ち上がります。普通のREPLとの違いは、そのsbtやplayのプロジェクト内で作ったクラスをREPLから呼び出すことができます。自分で作ったクラスの動作をREPL上から確認したいというときに便利。
最近、Scala勉強会 in 東京 #rpscalaで初心者向けセッションのコーナーが始まったみたいで初心者の方が参加しやすいタイミングとなっています(最初と最後に2回書いた)。
WrappedStringは知らなかったです。
後で追記しておきます。
ツッコミありがとうございます。