はじめに
下記のテキストを通して、基本的な書き方を学びつつ、個人的に気になったことを検証していくメモ代わりです。
https://dwango.github.io/scala_text/basic.html
本当にありがとう、dwango様・・・
Scalaの制御構文
http://qiita.com/tamagokake_gohan/items/ee2ce1157c5f4e646a66
の続き
ざっくりまとめ
- match式はbreakが無い代わりに
|
によって複数のOR条件をつけることが可能 - match式は型の識別ができるがObjectであることや、JVMの制約等があるため使用するときは注意が必要
match式
-
一般系
マッチ対象の式 match { case パターン1 [if ガード1] => 式1 case パターン2 [if ガード2] => 式2 case パターン3 [if ガード3] => 式3 case ... case パターンN => 式N }
-
使用方法
-
通常使用
scala> val name: String = "taro" name: String = taro scala> name match { | case "taro" => "Male" | case "Jiro" => "Male" | case "Hanako" => "Female" | } res18: String = Male
-
ワイルドカード
scala> val number1: Int = 1 number1: Int = 1 scala> val number2: Int = 2 number2: Int = 2 scala> val number3: Int = 3 number3: Int = 3 scala> number1 match { case 1 => "one"; case 2 => "two"; case _ => "other"} res22: String = one scala> number2 match { case 1 => "one"; case 2 => "two"; case _ => "other"} res23: String = two scala> number3 match { case 1 => "one"; case 2 => "two"; case _ => "other"} res24: String = other
-
型が違う場合
scala> val number1: Integer = 1 number1: Integer = 1 scala> number1 match { case 1 => "one"; case 2 => "two"; case _ => "other"} <console>:9: error: type mismatch; found : Int(1) required: Integer number1 match { case 1 => "one"; case 2 => "two"; case _ => "other"} ^
- errorとして返されるから注意が必要
-
C言語だとbreakがあるが、Scalaだと無いのでまとめる
scala> val str: String = "a" str: String = a scala> str match { case "a" => "A"; case "b" => "B"; } res25: String = A scala> str match { case "a" | "b" => "A or B"} res26: String = A or B
-
パターンマッチで値を取り出す
scala> val lst = List("A", "B", "C") lst: List[String] = List(A, B, C) scala> lst match { case List("A", b, c) => "A" + b + c; case _ => "other"} res27: String = ABC scala> lst match { case List(a, "B", c) => a + "B" + c; case _ => "other"} res28: String = ABC scala> lst match { case List("A", b, c) if b != "B" => "A" + b + c; case _ => "other"} res29: String = other
- case文内でif処理を同時にできるのは便利
- Listの途中であっても、判定可能(どこでも良いみたい)
-
ネストしている場合の取得
scala> val lst = List(List("N"), List("A", "B", "C")) lst: List[List[String]] = List(List(N), List(A, B, C)) scala> lst match { case List(n@List("N"), x) => n + x; case _ => "other"} <console>:9: error: type mismatch; found : List[String] required: String lst match { case List(n@List("N"), x) => n + x; case _ => "other"} ^ scala> lst match { case List(n@List("N"), x) => print(n) + print(x); case _ => "other"} <console>:9: error: type mismatch; found : Unit required: String lst match { case List(n@List("N"), x) => print(n) + print(x); case _ => "other"} ^ scala> lst match { case List(n@List("N"), x) => print(n) ; print(x); case _ => "other"} List(N)List(A, B, C)res32: Any = ()
- 検索対象は
@
で取り出すことが可能 -
;;
はちょっと気持ちが悪い(というより通常一行で書かないか・・・) - ついでに
print
の返り値はUnit型なのでString型の結合はできない
- 検索対象は
-
|
を使ったパターンマッチの場合は値を取り出すことができないscala> (List("a"): Any) match { case List(a) | Some(a) => println(a)} <console>:8: error: illegal variable in pattern alternative (List("a"): Any) match { case List(a) | Some(a) => println(a)} ^ <console>:8: error: illegal variable in pattern alternative (List("a"): Any) match { case List(a) | Some(a) => println(a)} ^ scala> val str: String = "a" str: String = a scala> str match { case a@"a" | a@"b" => a} <console>:9: error: illegal variable in pattern alternative str match { case a@"a" | a@"b" => a} ^ <console>:9: error: illegal variable in pattern alternative str match { case a@"a" | a@"b" => a} ^
- 組み合わせの場合取り出せないのは不便?
- そもそもそんな書き方をするのがナンセンスってことで弾かれていそう
- 組み合わせの場合取り出せないのは不便?
-
型によるパターンマッチ
scala> val target_s: String = "hoge" target_s: String = hoge scala> target_s match { case String => "is string"; case Integer => "is Integer"; case _ => "other"} <console>:9: error: object java.lang.String is not a value target_s match { case String => "is string"; case Integer => "is Integer"; case _ => "other"} ^ <console>:9: error: object java.lang.Integer is not a value target_s match { case String => "is string"; case Integer => "is Integer"; case _ => "other"}
- matchのcaseに対して型を直接入れることはできないっぽい
- 値じゃねーよって怒れる。まぁ、そうかw
scala> val target_s: String = "hoge" target_s: String = hoge scala> target_s match { case v:String => "is string"; case v:Integer => "is Integer"; case _ => "other"} <console>:9: error: scrutinee is incompatible with pattern type; found : Integer required: String target_s match { case v:String => "is string"; case v:Integer => "is Integer"; case _ => "other"} ^
- 対象の式に対して型が違うと怒られる
- Object型の式でないからかな?
scala> val target_s: AnyRef = "hoge" target_s: AnyRef = hoge scala> target_s match { case v:String => "is string"; case v:Integer => "is Integer"; case _ => "other"} res44: String = is string
- Object型ならマッチする
scala> val target_s: AnyRef = "hoge" target_s: AnyRef = hoge scala> target_s match { case String => "is string"; case Integer => "is Integer"; case _ => "other"} <console>:9: error: object java.lang.String is not a value target_s match { case String => "is string"; case Integer => "is Integer"; case _ => "other"} ^ <console>:9: error: object java.lang.Integer is not a value target_s match { case String => "is string"; case Integer => "is Integer"; case _ => "other"} ^
- ちなみに、対象の式がObject型であっても、パターンに対して変数を仕込む必要がある
scala> val target_s: AnyRef = "hoge" target_s: AnyRef = hoge scala> target_s match { case v:String => v + " is string"; case v:Integer => v + " is Integer"; case _ => "other"} res47: String = hoge is string
- match内部で変数を使用することが可能
scala> val target_s: AnyRef = "hoge" target_s: AnyRef = hoge scala> target_s match { case v@String => v + " is string"; case v@Integer => v + " is Integer"; case _ => "other"} <console>:9: error: object java.lang.String is not a value target_s match { case v@String => v + " is string"; case v@Integer => v + " is Integer"; case _ => "other"} ^ <console>:9: error: object java.lang.Integer is not a value target_s match { case v@String => v + " is string"; case v@Integer => v + " is Integer"; case _ => "other"} ^ scala> target_s match { case c@v:String => v + " is string"; case c@v:Integer => v + " is Integer"; case _ => "other"} <console>:1: error: '=>' expected but ':' found. target_s match { case c@v:String => v + " is string"; case c@v:Integer => v + " is Integer"; case _ => "other"} ^ <console>:1: error: '=>' expected but ':' found. target_s match { case c@v:String => v + " is string"; case c@v:Integer => v + " is Integer"; case _ => "other"} ^
- 遊び心で
@
や:
を組み合わせて見たが、エラーですねw
- matchのcaseに対して型を直接入れることはできないっぽい
-
JVMの制約による型のパターンマッチの落とし穴
scala> val obj: Any = List("a") obj: Any = List(a) scala> obj match { | case v: List[Int] => println("List[Int]") | case v: List[String] => println("List[String]") | } <console>:10: warning: non-variable type argument Int in type pattern List[Int] is unchecked since it is eliminated by erasure case v: List[Int] => println("List[Int]") ^ <console>:11: warning: non-variable type argument String in type pattern List[String] is unchecked since it is eliminated by erasure case v: List[String] => println("List[String]") ^ <console>:11: warning: unreachable code case v: List[String] => println("List[String]") ^ List[Int]
-
型変数を使った場合、正しくパターンマッチが実施されない
- 型変数を含む型のパターンマッチは、ワイルドカードパターンを使うとよいとのこと
obj match { case v: List[_] => println("List[_]") }
-
-