はじめに
もう既に何番煎じか(もうすぐ3桁?)て感じですが、敢えてもう1本上げてみる。
夕べ書いた ズンドコキヨシ.jl with Iteration を Elixir に翻訳してみた。
実装結果
zundoko.ex
# zundoko.ex
defmodule Zundoko do
def stream do
&stream(0, &1, &2)
end
defp stream(_, {:halt, acc}, _fun), do: {:halted, acc}
defp stream(v, {:suspend, acc}, fun), do: {:suspended, acc, &stream(v, &1, fun)}
defp stream(:done, {:cont, acc}, _fun), do: {:done, acc}
defp stream(5, {:cont, acc}, fun), do:
stream(:done, fun.("キ・ヨ・シ!", acc), fun)
defp stream(4, {:cont, acc}, fun), do:
stream(Enum.random([{4, "ズン"}, {5, "ドコ"}]), {:cont, acc}, fun)
defp stream(n, {:cont, acc}, fun) when n < 4, do:
stream(Enum.random([{n + 1, "ズン"}, {0, "ドコ"}]), {:cont, acc}, fun)
defp stream({n, zd}, {:cont, acc}, fun), do:
stream(n, fun.(zd, acc), fun)
def run do
stream |> Enum.join |> IO.puts
end
end
Zundoko.run
# => ズンドコズンズンズンドコドコドコズンドコドコズンズンズンズンズンズンズンズンドコキ・ヨ・シ!
ポイントは、「Stream
モジュールを使わないストリームの実装」。
(詳しくは 私の過去記事 等参照)
Zundoko.stream
の定義に Enum.random
以外の標準ライブラリ関数を使用していません!
ズンドコキヨシ.jl with Iteration と同様、処理本体は Stream
(として扱われる関数)として返ってくるので、リストで取得したければ、例えば
Zundoko.stream |> Enum.to_list
とすれば ["ドコ", "ズン", "ドコ", "ズン", "ズン", "ズン", "ズン", "ズン", "ドコ", "キ・ヨ・シ!"]
といったリストが得られます。
まとめじゃないけれど
ストリーム(無限リスト)やイテレータの定義方法が似ているなら他言語でも同じような感じで実装出来るのではないかと。