読者です 読者をやめる 読者になる 読者になる

opamp_sando's blog

クソザコが割りと適当なことを書くためにある備忘録です。あとたまに普通の日記も書きます

scalaのmatch式 その2

続き
ListやArrayのようなシーケンス型と呼ばれるものに対しても次のようなmatchがかける...

val l = List(1,2,3,4)

l match {
    case List(0,_,_,_) => println("0から始まって長さ4のリスト")
    case List(1,_,_) => println("1から始まって長さ3のリスト")
    case List(1,_*) => println("1から始まって長さ1以上のリスト")
    case _ => println("something else...")
}

これを実行すると、上から3つ目のcaseに引っかかる。まあ、特に説明をしなくても多分直感的に理解できると思う。
ちなみに"*"は任意の長さにマッチするが0個でもマッチする。
あと、タプルも似たような感じでcaseにかけるがタプルでは"
*"は使えない。

  また、型を使ったmatchも可能である。

def hoge(x:Any){
    x match {
       case _:Int => println("Int")
       case _:Double => println("Dobule")
       case _:String => println("String")
       case _ => println("Unknown")
    }
}

hoge(1)     // => Int
hoge(1.2)   // => Double
hoge("A")   // => String
hoge((1,2)) // => Unknown

という感じ。
大学の図書館から借りてきたscala本によれば、これを使えば型チェック->型キャストができる。
まずcaseの時点で「Intならば」とか「Stringならば」という具合にチェックしている。 そして上の例では"_"を用いたがその部分をaやらbやら適当な変数に書き換えることで、型キャストも行える。

x match {//x is Any
    case s:String => println(s + " is String")
    case i:Int => println(i.toString + " is Int")
    case _ => println("else")
}

と、例えばこんな具合。こうすることでxがAny型であっても、Stringならmatch中の1行目でmatchして自動でsにStringとして型変換されて右辺で使うことができる。

ちなみに、Scalaには型チェックと型キャストをする関数が存在する。それぞれisInstanceOf関数とasInstanceOf関数という。 だが、これら2つを使うと記述が冗長になり見にくい。ということで、推奨されないらしい。
ので、このような場合には上のようにmatchを用いることを推奨している。

で、話は変わって変数の束縛...について。
matchのcase内で"@"を使うことで変数を束縛できる。

変数名 @ パターン

という順番で記述する。簡単な例をあげる。

val l = List(1,3,5,7)

l match {
    case List(_,a @ 3,_*) => printf("match: a is %d",a)
    case _ => println("no match")
}

という具合。これはList(○,3,....)に合うようなリストにマッチする。つまり、はじめの要素があり(値はなんでもいい)、次の要素の値が3であり、その後0個以上の要素が続くList。
これがmatchした場合、右辺のaは3に束縛される。
もし与えるListの2番目の要素が3でないならmatchせずにcase _が処理される。

ということで、かなり本質に届いてない気しかしないけど大まかなmatchの使い方は以上かな。
とりあえず、今後何かミスやもっといい書き方があれば更新したりその3を書いたりするかもしれない。
とりあえず今日はこれで。

Firefox ブラウザ無料ダウンロード