Akihito Ikeda

0.5ミクロン分のElixirにふれたよ

posts/2020-12-21diary

今日も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

headtailにわけられるということはこうやってreverseを実装できる(パターンマッチ、再帰の組み合わせ)。

def reverse([]), do: []
def reverse([head | tail]), do: reverse(tail) ++ [head]

まあこの辺りはそりゃそうって感じか〜。

© Akihito Ikeda - Last update 23.07.2021 17:02.