モーダルを閉じる工作HardwareHub ロゴ画像

工作HardwareHubは、ロボット工作や電子工作に関する情報やモノが行き交うコミュニティサイトです。さらに詳しく

利用規約プライバシーポリシー に同意したうえでログインしてください。

工作HardwareHub ロゴ画像 (Laptop端末利用時)
工作HardwareHub ロゴ画像 (Mobile端末利用時)

Scala 組み込みの制御構造

モーダルを閉じる

ステッカーを選択してください

モーダルを閉じる

お支払い内容をご確認ください

購入商品
」ステッカーの表示権
メッセージ
料金
(税込)
決済方法
GooglePayマーク
決済プラットフォーム
確認事項

利用規約をご確認のうえお支払いください

※カード情報はGoogleアカウント内に保存されます。本サイトやStripeには保存されません

※記事の執筆者は購入者のユーザー名を知ることができます

※購入後のキャンセルはできません

公開日公開日
2015/04/02
最終更新最終更新
2021/10/07
記事区分記事区分
一般公開

目次

    アカウント プロフィール画像 (サイドバー)

    Scalaはいいぞ

    0
    ステッカーを贈るとは?

    if-else

    条件分岐で知られる 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
    

    while は非推奨

    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)
      }
    }
    

    foreach

    object HelloWorld {
      def main(args: Array[String]): Unit = {
        args.foreach{arg =>
          // ループ風
          println(arg)
        }
    
        // 略記法
        args.foreach(println)
      }
    }
    

    for はとても優秀

    List

    object HelloWorld {
      def main(args: Array[String]): Unit = {
        val list = List(1,2,3)
        for(e <- list) {
          println(e)
        }
      }
    }
    

    to, until

    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)
      }
    }
    

    if による抽出

    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 の中で for

    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
      }
    }
    

    match

    他の言語の 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) => {
          }
        }
      }
    }
    

    if で条件を指定 (パターンガード)

    一致しなければいつも通り次の 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
      }
    }
    

    型でマッチ

    object HelloWorld {
      def main(args: Array[String]): Unit = {
        val myVal: Any = List(1,2,3)
        myVal match {
          case x: Int => {
          }
          case x: String => {
          }
          case x: List[_] => {
            println(x) //=> List(1, 2, 3)
          }
          case _ => {
          }
        }
      }
    }
    

    case class

    object HelloWorld {
      def main(args: Array[String]): Unit = {
        case class MyCaseClass(prop1: Int, prop2: String)
        val obj = new MyCaseClass(0, "ABC")
        obj match { //=> prop1: 0, prop2: ABC
          case MyCaseClass(1, _) => {
          }
          case MyCaseClass(_, "abc") => {
          }
          case MyCaseClass(prop1, prop2) => { // 変数バインド
            println("prop1: %d, prop2: %s" format (prop1, prop2))
          }
        }
    
        case class MyCaseSuperClass(prop1: Int, prop2: MyCaseClass)
        val obj2 = new MyCaseSuperClass(123, obj)
        obj2 match { //=> MyCaseClass(0,ABC)
          case MyCaseSuperClass(prop1, MyCaseClass(_, "abc")) => {
          }
          case MyCaseSuperClass(prop1, matchedObj @ MyCaseClass(_, _)) => { // '@' で case class ごとバインド
            println(matchedObj)
          }
          case _ => {
          }
        }
      }
    }
    

    break-continue

    scala には break-continue がありません。再帰関数などで処理を実現することが推奨されています。どうしても必要だと感じた場合には標準ライブラリをインポートすることで break は使用できるようになります。

    import scala.util.control.Breaks._
    import java.io._
    
    object HelloWorld {
      def main(args: Array[String]): Unit = {
        val in = new BufferedReader(new InputStreamReader(System.in))
        breakable {
          while(true) {
            val line = in.readLine()
            println(line)
            if(line == "") break
          }
        }
      }
    }
    

    break で例外が投げられて breakable でキャッチする作りになっていることを利用した (バッド) ノウハウを用いれば continue も実現できます。

    import scala.util.control.Breaks.{break => continue, breakable => continuable}
    
    object HelloWorld {
      def main(args: Array[String]): Unit = {
        for(i <- 1 to 5) {
          continuable {
            if(i % 2 == 0) {
              continue
            }
            println(i) // 1,3,5
          }
        }
      }
    }
    
    0
    詳細設定を開く/閉じる
    アカウント プロフィール画像 (本文下)

    Scalaはいいぞ

    記事の執筆者にステッカーを贈る

    有益な情報に対するお礼として、またはコメント欄における質問への返答に対するお礼として、 記事の読者は、執筆者に有料のステッカーを贈ることができます。

    さらに詳しく →
    ステッカーを贈る コンセプト画像

    Feedbacks

    Feedbacks コンセプト画像

      ログインするとコメントを投稿できます。

      関連記事

      • Scala 文字列の処理
        書式指定 object Main { def main(args: Array[String]): Unit = { println("%d + %d = %d".format(1, 1, 2)) //=> 1 + 1 = 2 } } 文字列の比較 ヒアドキュメント 他の言語でいう「ヒアドキュメント」のようなものは """ で囲うことで実現できます。 object Main ...
        したくんしたくん6/18/2018に更新
        いいねアイコン画像0
      • Scala 日付に関する処理
        Date クラスを文字列にフォーマット import java.util.Date object Main { def main(args: Array[String]): Unit = { // format は Date に限らない文字列用の機能です。 println("%d-%d-%d" format (1, 1, 1)) //=> 1-1-1 printl...
        したくんしたくん6/5/2018に更新
        いいねアイコン画像0
      • 酢豚の基本的な使い方 (sbt)
        sbt は Scala および Java を主な対象としたビルドツールです。Scala Build Tool の略ではありませんが、Simple Build Tool という明示的な記述も公式ドキュメントなどには見当りません。以下 sbt の基本的な使用例をまとめます。使用した sbt のバージョンは 0.13 です。 公式ドキュメント [sbt 0.13](http://www.scala-sb...
        ねこねこ6/30/2018に更新
        いいねアイコン画像0
      • Scala 関数のサンプルコード
        「デフォルト引数」および「Unit 型を返す関数」 object HelloWorld { def main(args: Array[String]): Unit = { def myPrint(myArg: String = "default_value") = println(myArg + "!") val result = myPrint() //=> defau...
        したくんしたくん6/26/2018に更新
        いいねアイコン画像0
      • Scala の基本文法
        Scala は JVM 上で動作するバイトコードにコンパイルできる言語です。JAVA よりも柔軟な記述ができます。事前にこちらからダウンロードおよびインストールしておいてください。基本的な文法をまとめます。 変数および定数 object HelloWorld { def main(args: Array[String]): Unit = { val constVal = 1 //
        したくんしたくん10/7/2021に更新
        いいねアイコン画像0