0.5ミクロン分のElixirにふれたよ
今日も0.5ミクロンだけElixirと触れ合った。社内の競プロチャンネルでちょっと話題に出ていた問題をやってみた。
https://atcoder.jp/contests/abc185/submissions/18926690
これB問題だけどけっこうむずくて、特にEnum.reduce_while/3
を使うことを先に決めてたので、accumulatorをどう置くかを少し悩んでしまった。結局負けた気分になりながら配列的なものにして二つの値を参照・更新するようにしたけど、もうちょいうまくやれそうな気がしなくもない。この辺りのうまさってのは慣れたら上達していくものなんだろうか…。
あと上のリンク先にあるコード例でいうと、この部分がすき。
...
|> ans()
end
def ans(n) when n > 0, do: "Yes"
def ans(_), do: "No"
ふわっとした言葉で表現すると、あとはよろって感じでans()
に投げて、ans()
はans()
で手続き的にYes/No
を出力しわけるのではなくてあくまでパターンマッチ(Elixir的にはガード)的にただそこに定義が置いてあるだけ、あとはいい感じ言語自体がやってくれる、みたいな感じがすき。
そういう例でいうとHaskellのパターンマッチもきもちよくてすき。
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial (n - 1)
head' :: [a] -> a
head' [] = error "List is empty."
head' (x:xs) = x
tail' :: [a] -> [a]
tail' [] = error "List is empty."
tail' (x:xs) = xs
こういうの。
Elixirでも似たようなことはできる。
def head([head | _]), do: head
def tail([_ | tail]), do: tail
head
とtail
にわけられるということはこうやってreverse
を実装できる(パターンマッチ、再帰の組み合わせ)。
def reverse([]), do: []
def reverse([head | tail]), do: reverse(tail) ++ [head]
まあこの辺りはそりゃそうって感じか〜。