Scala は JVM 上で動作するバイトコードにコンパイルできる言語です。JAVA よりも柔軟な記述ができます。事前にこちらからダウンロードおよびインストールしておいてください。基本的な文法をまとめます。
詳細は『Scala の型に関する知識』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
val constVal = 1 // 定数
var variableVal = 1 // 変数
val intVal: Int = 1 // 型指定定数
var intVar: Int = 1 // 型指定変数
// 基本的な型
val longVal = 1L
val floatVal = 1.0f
val doubleVal = 1.0
val charVal = 'a'
val stringVal = "string"
val nullVal = null
// Any 型 (Scala の全ての親クラス)
// 関連情報: https://www.qoosky.io/techs/3fef7fa668
val a: Any = 1
a.asInstanceOf[Int] // キャスト
}
}
詳細は『Scala 組み込みの制御構造』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
if (true) {
println("true")
}
else {
println("false")
}
val myval = if (true) 1 else 0
}
}
詳細は『Scala 組み込みの制御構造』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
var i = 0
while(i < 10) {
i = i + 1
}
i = 0
do {
i = i + 1
} while (i < 10)
}
}
詳細は『Scala 関数のサンプルコード』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
val result = {
val a = 1
val b = 2
a + b
}
println(result) //=> 3
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
def myFunc1(a: Int, b: Int): Int = {
return a + b
}
def myFunc2(a: Int, b: Int): Int = {
a + b
}
def myFunc3(a: Int, b: Int) = {
a + b
}
def myFunc4(a: Int, b: Int) = a + b
def myFunc5 = 3
println(myFunc1(1,2)) //=> 3
println(myFunc2(1,2)) //=> 3
println(myFunc3(1,2)) //=> 3
println(myFunc4(1,2)) //=> 3
println(myFunc5) //=> 3
}
}
引数なしコンストラクタ
object HelloWorld {
def main(args: Array[String]): Unit = {
class MyClass {
val prop = 1
def method(arg: Int) = prop + arg
}
val obj = new MyClass
println(obj.method(2)) //=> 3
}
}
引数ありコンストラクタ
object HelloWorld {
def main(args: Array[String]): Unit = {
class MyClass(_arg: Int) {
val prop = _arg
def method(arg: Int) = prop + arg
}
val obj = new MyClass(1)
println(obj.method(2)) //=> 3
}
}
コンストラクタに記載した処理はインスタンスを生成したタイミングで実行されます。
object HelloWorld {
def main(args: Array[String]): Unit = {
class MyClass {
println(123)
}
val obj = new MyClass //=> 123
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
// 親クラス
class MyClass {
val prop1 = 123
var prop2 = "abc"
def method: Unit = println("MyClass")
}
// インスタンス化
val obj = new MyClass
println(obj.prop1) //=> 123
obj.prop2 = "xyz" // 'var' にはセッターがある
println(obj.prop2) //=> xyz
// 子クラス
class MySubClass extends MyClass {
override val prop1 = 456 // val には 'override' が必要
prop2 = "xyz" // var には 'override' は不要 (というよりは「上書きする」)
override def method: Unit = { //メソッドのオーバーライド
super.method // 親クラスは super で参照
println("MySubClass")
}
final val prop3: String = "final でオーバーライドできなくする。"
}
val obj2 = new MySubClass
obj2.method //=> MyClass\nMySubClass
println(obj2.prop1) //=> 456
println(obj2.prop2) //=> xyz
println(obj2.prop3) //=> final でオーバーライドできなくする。
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
abstract class MyAbstractClass {
val prop: String
def method(arg: Int): Int
}
class MyConcreteClass extends MyAbstractClass {
val prop: String = "abc"
def method(arg: Int): Int = {
arg + 1
}
}
val obj = new MyConcreteClass
println(obj.prop) //=> abc
println(obj.method(1)) //=> 2
}
}
クラスオブジェクトを比較して検証できます。isInstanceOf を利用したほうがスマートです。
object HelloWorld {
def main(args: Array[String]): Unit = {
val i = 123
println(classOf[Int]) //=> int
println(i.getClass == classOf[Int]) //=> true
}
}
import scala.language.reflectiveCalls
object HelloWorld {
def main(args: Array[String]): Unit = {
val obj = new {
val prop = 123
}
println(obj.prop) //=> 123
}
}
『Singletonパターンの実装例 (Java)』は Scala では Object で実現できます。
object HelloWorld {
def main(args: Array[String]): Unit = {
object Singleton {
val prop = 123
}
println(Singleton.prop) //=> 123
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
type MyType[A] = List[List[A]]
val obj: MyType[Int] = List(List(1), List(2))
println(obj) //=> List(List(1), List(2))
type Three[A] = Tuple3[A, A, A]
type M[A, B] = scala.collection.mutable.Map[A, B]
}
}
C++ クラステンプレート のように型を既定しないクラスを実装できます。
object HelloWorld {
def main(args: Array[String]): Unit = {
class MyClass[A] {
var list: List[A] = Nil
}
val obj = new MyClass[Int]
obj.list = 1 :: obj.list
obj.list = 2 :: obj.list
println(obj.list) //=> List(2, 1)
}
}
詳細は『Scala コレクション』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
val intArr = new Array[Int](10)
for(elem <- intArr) {
println(elem)
}
}
}
可変長の配列です。リストと異なり配列ですのでインデックスで指定した要素へのアクセスは高速ですが、要素の追加や削除の処理は現在のサイズ分のメモリ領域を新しく確保しなおす必要があるため低速です。
object HelloWorld {
def main(args: Array[String]): Unit = {
import scala.collection.mutable.ArrayBuffer
val buf = new ArrayBuffer[Int]()
buf += 1
buf += 2
3 +=: buf
println(buf) //=> ArrayBuffer(3, 1, 2)
}
}
詳細は『Scala コレクション』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
// これは配列
val intArr = new Array[Int](2)
intArr(0) = 10
intArr(1) = 20
println(intArr(0)) //=> 10
println(intArr(1)) //=> 20
// 以下はリスト
// Nil と空リストは等しい
println(List() == Nil) //=> true
// リストを結合で生成
val list = 1 :: 2 :: List(3,4) ::: List(5,6)
println(list) //=> List(1, 2, 3, 4, 5, 6)
println(list(0)) //=> 1
println(1 :: 2 :: Nil) //=> List(1, 2) 空のリスト Nil の先頭に要素を追加
val newList1 = list :+ 1 // 末尾に追加
val newList2 = 1 +: list // 先頭に追加
println(newList1 ++ newList2) // 連結 (リストの場合は ::: でもよい)
println(list ++ intArr) // 左辺の型 List になる
println(list ++: intArr) // 右辺の型 Array になる
// カウント
println(list.count(s => s < 6)) //=> 5
println(list.count{ _ < 6 }) //=> 5
// 存在確認
println(list.exists{ _ == 1 }) //=> true
println(list.contains(0)) //=> false
// すべてが〜である、かどうか
println(list.forall{ _ > 0 }) //=> true
// 先頭の要素、最後の要素
println(list.head) //=> 1 (空のリストでは例外)
println(list.last) //=> 6 (空のリストでは例外)
println(Nil.headOption) //=> None
println(Nil.lastOption) //=> None
// 先頭を除いたリスト、最後を除いたリスト
println(list.tail) //=> List(2, 3, 4, 5, 6)
println(list.init) //=> List(1, 2, 3, 4, 5)
// 先頭から N 個取得または破棄
println(List(1,2,3,4,5).take(2)) // 先頭から二つ List(1, 2)
println(List(1,2,3,4,5).drop(2)) // 先頭から二つを除いたもの List(3, 4, 5)
println(List(1,2,3,4,5).takeWhile{ _ < 4 }) //=> List(1, 2, 3)
println(List(1,2,3,4,5).dropWhile{ _ < 4 }) //=> List(4, 5)
// 一定範囲のみを取得
println(List("a", "b", "c", "d", "e").slice(2, 4)) // slice(i,j) = List(Ei, Ei+1,..., Ej-1)
//=> List(c, d)
// 空であるかどうか (一つだけ見ればよいため size == 0 より高速)
println(list.isEmpty) //=> false
println(list.nonEmpty) //=> true
// リストの長さ
println(list.length) //=> 6
println(list.size) //=> 6
// マップ
println(list.map{ _ * 2 }) //=> List(2, 4, 6, 8, 10, 12)
// 文字列の生成 (Join のようなもの)
println(list.mkString(", ")) //=> 1, 2, 3, 4, 5, 6
// 逆転
println(list.reverse) //=> List(6, 5, 4, 3, 2, 1)
// 要素の削除 (フィルタリングして除外して新たなリストを作成)
println(list.filter{ _ == 1 }) //=> List(1)
println(list.filterNot{ _ > 2 }) //=> List(1, 2)
// ソート
println(list.sortWith((s,t) => s < t)) // sort
//=> List(1, 2, 3, 4, 5, 6)
// map でチェーンする場合に高速化
// (中間 List を生成せずに map も適用しながら filter するため withFilter が高速)
val result = list.filter { _ != 1 } map { _.toString }
val result2 = list.withFilter { _ != 1 } map { _.toString }
println(result) //=> List(2, 3, 4, 5, 6)
println(result2) //=> List(2, 3, 4, 5, 6)
}
}
リストはその性質上、末尾へのアクセスが遅くなります。末尾への要素の追加が頻繁に発生して速度が気になる場合はリストバッファーを使用します。
object HelloWorld {
def main(args: Array[String]): Unit = {
import scala.collection.mutable.ListBuffer
val buf = new ListBuffer[Int]
buf += 10
buf += 20
30 +=: buf
println(buf) //=> ListBuffer(30, 10, 20)
val list = buf.toList
println(list) //=> List(30, 10, 20)
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
// タプルには異なる型が格納できる
val pair: Tuple2[Int, String] = (99, "This is a string.")
println(pair._1 + 1) //=> 100
println(pair._2 + 1) //=> This is a string.1
// 例えば、リストではできない (Any になる)
// [参考] Scala の型に関する知識 https://www.qoosky.io/techs/297
val list: List[Any] = List(99, "This is a string.")
println(list.head.asInstanceOf[Int] + 1) // Any からキャストする必要がある
println(list.last.asInstanceOf[String] + 1) // Any からキャストする必要がある
// 型を明記する例
val tuple:(Int,Int) = (1, 2)
// 値の取得
val (intValA, intValB) = tuple
println(intValA) //=> 1
println(intValB) //=> 2
println(tuple._1) //=> 1
println(tuple._2) //=> 2
tuple match {
case(intValC, intValD) => {
println(intValC) //=> 1
println(intValD) //=> 2
}
}
}
}
詳細は『Scala コレクション』をご参照ください。
object HelloWorld {
def main(args: Array[String]): Unit = {
// 集合
import scala.collection.mutable.Set
val mySet = Set("A", "B")
mySet += "C"
println(mySet.contains("C")) //=> true
// 連想配列
import scala.collection.mutable.Map
val myMap = Map[String, Int]()
myMap += ("A" -> 1)
myMap += ("B" -> 2)
println(myMap("B")) //=> 2
val myMap2 = Map(
"a" -> 10,
"b" -> 20
)
println(myMap2) //=> Map(b -> 20, a -> 10)
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
// 連想配列
val myMap = Map(
"a" -> 10,
"b" -> 20
)
// キーが存在する場合
println(myMap("a")) //=> 10
println(myMap.get("a")) //=> Some(10)
println(myMap get "a") //=> Some(10)
// キーが存在しない場合
// println(myMap("c")) //=> java.util.NoSuchElementException
println(myMap.get("c")) //=> None
// Option 型はパターンマッチで条件分岐
// ( Scala の Option[T] は null と比較しても意味がないため
// Java のように if-else で null 判定してはならない )
def show(x: Option[Int]) = x match {
case Some(i) => i
case None => null
}
println(show(myMap get "a")) //=> 10
println(show(myMap get "c")) //=> null
// Option 型は Some で囲えば作れる
println(Some(1)) //=> Some(1)
println(None) //=> None
}
}
Option 型の便利なメソッド
object HelloWorld {
def main(args: Array[String]): Unit = {
val option: Option[Int] = Some(123)
val option2: Option[Int] = null
val option3: Option[Int] = None
// Map の get と区別。Option 型の get
println(option.get)
// println(option2.get) // java.lang.NullPointerException
// println(option3.get) // java.util.NoSuchElementException: None.get
// 以下 null はすべて例外を投げるため除外:
// 定義済みかどうかを判定
println(option.isEmpty) //=> false
println(option.isDefined) //=> true
println(option3.isEmpty) //=> true
println(option3.isDefined) //=> false
// None の場合に null または指定した値を返す
println(option.orNull) //=> 123
println(option.getOrElse(-1)) //=> 123
println(option3.orNull) //=> null
println(option3.getOrElse(-1)) //=> -1
// None の場合は処理しない
option.foreach{ value: Int =>
println(value) //=> 123
}
option3.foreach{ value: Int =>
println(value) // None のため実行されない
}
}
}
詳細は『Scala ファイル関連の処理』をご参照ください。
import scala.io.Source
object HelloWorld {
def main(args: Array[String]): Unit = {
if(args.length > 0) {
for(line <- Source.fromFile(args(0)).getLines())
println(line.length + " " + line)
}
else
Console.err.println("Please enter filename")
}
}