テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

(elixir report) 同じ形のパターンマッチ

OCamlでは, pat1とpat2が似ていて, ->の先で使う束縛変数が同じ場合に, 以下のように書くことが出来る.

match x with
  | pat1
  | pat2 -> 

Elixirではこの記法は出来ない. しかし, IRCで聞いたところ, guardを使えば似たようなことは出来るようになる. 以下のような形.

case x do
 {t, a} when t in [:a, :b] -> a

この疑問は, MAL実装において, listとvectorに対してやることは同じだから, マッチングのところで統一して出来たらいいじゃないかと思ったことに発端する.

例えば, Haskell実装は以下のように重複している. ただし私はHaskellのことは記憶が曖昧なので, 実はOCamlのように書けるのではと疑っている.

quasiquote :: MalVal -> MalVal
quasiquote ast =
    case ast of
         (MalList (MalSymbol "unquote" : a1 : []) _) -> a1
         (MalList (MalList (MalSymbol "splice-unquote" : a01 : []) _ : rest) _) ->
            MalList [(MalSymbol "concat"), a01, quasiquote (MalList rest Nil)] Nil
         (MalVector (MalList (MalSymbol "splice-unquote" : a01 : []) _ : rest) _) ->
            MalList [(MalSymbol "concat"), a01, quasiquote (MalVector rest Nil)] Nil

OCamlのコードはスマートだ.

    | T.List   { T.value = T.List { T.value = [T.Symbol {T.value = "splice-unquote"}; head]} :: tail }
    | T.Vector { T.value = T.List { T.value = [T.Symbol {T.value = "splice-unquote"}; head]} :: tail } ->
       Types.list [Types.symbol "concat"; head; quasiquote (Types.list tail)]

だがこのコードもElixirであればもっと短く書ける. こんな形になるだろう

t { .....} when t in [list, vector] ->

ところで私はパターンマッチが好きだ. 次に仕事をするとしたら, パターンマッチのある言語がいい. Rustでももちろんいい.

Chao