条件分岐で知られる if-else は三項演算子のようにも使用されます。
object HelloWorld {
def main(args: Array[String]): Unit = {
val myVal =
if (!args.isEmpty) args(0)
else "default"
println(myVal)
}
}
実行例
$ scala sample.scala
default
scala において while は極力使用せずに別の手段で代用できないか考えるとよいとされます。例えば他の言語でよく用いられる
var tmp = null
while((tmp = myFunc()) != null)
println(tmp)
といった形式のコードは動作しません。なぜならば scala において代入の結果は Unit 型の値となるからです。Unit 型の値とはすなわち () のことであり他の言語でいうところの void のようなものです。
object HelloWorld {
def main(args: Array[String]): Unit = {
var tmp = ""
println(tmp = "test") //=> ()
}
}
while を使用するためにはどうしてもミュータブルな変数 var
が必要になってしまい Scala らしいイミュータブルなコードになりません。
object HelloWorld {
def main(args: Array[String]): Unit = {
var i = 0
while(i < 2) {
println(i)
i = i + 1
}
do {
println(i)
i = i - 1
} while(i > 0)
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
args.foreach{arg =>
// ループ風
println(arg)
}
// 略記法
args.foreach(println)
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
val list = List(1,2,3)
for(e <- list) {
println(e)
}
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
for(i <- 1 to 4) { // 1,2,3,4
println(i)
}
for(i <- 1 until 4) { // 1,2,3
println(i)
}
for(i <- 1 until (10, 3)) { // 1,4,7 (3つ飛ばし)
println(i)
}
val range = Range(1, 10, 3) // こう書いても同じ
for(i <- range) { // 1,4,7
println(i)
}
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
val list2 = for(e <- list if e % 2 == 0) yield e * 2
println(list2) //=> List(4, 8)
val list3 = for {
i <- 1 to 10
if i % 2 == 0
} yield i
println(list3) //=> Vector(2, 4, 6, 8, 10)
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
val files = (new java.io.File(".")).listFiles
for(file <- files if file.getName.endsWith(".scala"))
println(file)
for(
file <- files
if file.isFile
if file.getName.endsWith(".scala")
) println(file)
}
}
for 文の入れ子をシンプルに記述できます。
object HelloWorld {
def main(args: Array[String]): Unit = {
// (0,0), (0,1), (1,0), (1,1)
for(i <- 0 to 1) {
for(j <- 0 to 1) {
println("i: %d, j: %d".format(i,j))
}
}
for(i <- 0 to 1; j <- 0 to 1) {
println("i: %d, j: %d".format(i,j))
}
for {
i <- 0 to 1
j <- 0 to 1 }{
println("i: %d, j: %d".format(i,j))
}
}
}
少し複雑な例
object HelloWorld {
def main(args: Array[String]): Unit = {
grep(".*grep.*")
}
def grep(pattern: String): Unit = {
for {
file <- (new java.io.File(".")).listFiles
if file.getName.endsWith(".scala")
line <- scala.io.Source.fromFile(file).getLines().toList
trimmed = line.trim
if trimmed.matches(pattern)
} println(file + ": " + trimmed)
}
ネストした List などの処理にも便利です。
object HelloWorld {
def main(args: Array[String]): Unit = {
val nestedList: List[List[String]] = List(
List("A", "B"),
List("a", "b")
)
for(l <- nestedList; e <- l if e == "a") println(e) //=> a
}
}
他の言語の switch-case のようなものです。値を返すこともできます。
object HelloWorld {
def main(args: Array[String]): Unit = {
val myVal = "abc"
myVal match { //=> 1
case "abc" => println(1)
case "def" => println(2)
case _ => println(-1)
}
val myVal2 =
myVal match {
case "def" => "DEF"
case _ => "default"
}
println(myVal2) //=> default
}
}
_
の代わりに変数名を指定したバインドができます。その際の変数名は小文字から始まっている必要があります。大文字で始まる場合は定数とみなされて、値を比較されます。
object HelloWorld {
def main(args: Array[String]): Unit = {
val myVal = "abc"
myVal match { //=> abc
case "dummy" => {
}
case x => {
println(x)
}
}
val MyVal = "xyz"
myVal match { //=> default
case MyVal => {
}
case _ => {
println("default")
}
}
// 小文字開始の場合で、値を比較したい場合はバッククォートで囲みます。
val myVal2 = "abc"
myVal match { //=> myVal == myVal2
case `myVal2` => {
println("myVal == myVal2")
}
case _ => {
}
}
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
val pattern = """(\d{4})/(\d{2})/(\d{2})""".r
val str = "1999/12/31"
str match { //=> str == 1999/12/31
case pattern("1999", "12", "31") => {
println("str == 1999/12/31")
}
case pattern(year, month, day) => {
}
}
}
}
一致しなければいつも通り次の case の判定に移ります。
object HelloWorld {
def main(args: Array[String]): Unit = {
val myVal = "abc"
myVal match { //=> abc
case x if x == "abc" => {
println(x)
}
case _ => {
}
}
}
}
object HelloWorld {
def main(args: Array[String]): Unit = {
// リスト
val list = List(1, 2, 3)
list match { //=> hi
case List(1, 2, 3) => {
println("hi")
}
case List(x, y, z) => { // バインド
}
case List(_, _) => { // 要素数が二つ
}
case List(0, _*) => { // 先頭の要素の値が 0 で、長さが任意のリスト
}
case _ => {
}
}
// 配列も同様
val arr = Array(1, 2, 3)
arr match {
case Array(1, 2, 3) => {
}
case _ => {
}
}
// タプル
val tuple = (0, 1)
tuple match { //=> (0, 1)
case (1, 2) => {
}
case (1, _) => {
}
case (x, y) => {
println("(%d, %d)" format (x,y))
}
}
}
}
再帰処理
object HelloWorld {
def main(args: Array[String]): Unit = {
def rec(list: List[Int]): Int = {
list match {
case x :: xs => {
x * rec(xs) // 先頭の要素 :: 残りの要素からなるリスト
}
case Nil => {
1
}
}
}
println(rec(List(1,2,3))) //=> 6
}
}