技術のメモ帳

気が向いたときに書いてます

elixir学習日誌: 再帰とStream

再帰

末尾再帰とは?

defmodule Person do
  def say(message, n) when n == 1 do
    IO.puts message
  end

  def say(message, n) do
    IO.puts message
    say message, n - 1 # ←この部分が末尾再帰
  end
end
Person.say "Hello", 3
# => Hello
# => Hello
# => Hello
  • 末尾再帰にすると、スタックを積まないので、リソースの無駄使いをしない。

Enumerable

  • Enumerableとは「列挙可能」という意味。
  • リストやマップは、Enumerableな構造データ。
Enum.map %{ first_name: "taro", family_name: "yamada" }, fn {k, v} -> "#{k} is #{v}" end
# => ["family_name is yamada", "first_name is taro"]

パイプ演算子

["foo", "bar", "baz"] |> Enum.map(fn x -> x <> x end) |> Enum.reduce("", fn x, result -> result <> x end)
# => "foofoobarbarbazbaz"
  • |> は、|>の左側を、右側の第一引数として渡すための演算子
  • 一時変数を書かずに、記述できる(関数型言語らしい)。
  • カリー化のような雰囲気。

Stream

m = ["foo", "bar", "baz"]

IO.inspect m |> Enum.filter(fn x -> x in ["foo", "bar"] end) |> Enum.map(fn x -> x <> x end)

s = m |> Stream.filter(fn x -> x in ["foo", "bar"] end) |> Stream.map(fn x -> x <> x end)
IO.inspect Enum.to_list s
  • Streamを使うと、遅延評価され、to_listで呼び出されるまで、リストの中身を列挙する処理は実行されない。
  • Streamは、毎回列挙せず、一度限りの列挙となる(遅延評価しない場合は、毎回列挙することになる)。

参考