ズンドコキヨシ with Elixir Stream

  • 8
    Like
  • 0
    Comment
More than 1 year has passed since last update.

はじめに

流行りに乗ってみました。すでにn番煎じでした。すいません
しかも仕様を間違えて永遠に続けられるようにしてしまいました。
でもStreamモジュールの勉強になりました。

Streamとは

Elixirにはリスト用のモジュールとして即時評価なEnumモジュールと遅延評価なStreamモジュールがあります。
今回Streamモジュールをつかった遅延評価な感じで実装してみました。

常に5word分バッファしながら動きバッファの内容が条件にマッチングしたら
キ・ヨ・シ!をリストに追加します。

実装結果は以下のとおりです。

defmodule Zundoko do
  @zun "ズン "
  @doko "ドコ "
  @kiyoshi "キ・ヨ・シ!"
  def try(n) do
    zundoko |> kiyoshi |> Enum.take(n) |> IO.puts
  end
  def zundoko do
    Stream.repeatedly(fn -> Enum.random([@zun, @doko]) end)
  end

  def kiyoshi(zundoko) do
    zundoko |> Stream.transform([], fn e, acc ->
      if Enum.count(acc) < 5 do
        {[e], [e|acc]}
      else 
        [_ | tail] = Enum.reverse(acc)
        next_acc = Enum.reverse(tail)
        case Enum.reverse(acc) do
          [@zun,@zun,@zun,@zun,@doko] -> {[@kiyoshi,e],[e | next_acc]}
          _ -> {[e],[e | next_acc]}
        end
      end        
    end)
  end
end

順に説明します

zundoko

無限長のリストを作成します。
randomにズン,ドコを吐き出し続けることが可能です。

  def zundoko do
    Stream.repeatedly(fn -> Enum.random([@zun, @doko]) end)
  end

個別に実行すると次のようになります。

iex(67)> Zundoko.zundoko |> Enum.take(5)
["ドコ ", "ズン ", "ズン ", "ズン ", "ズン "]
iex(68)> Zundoko.zundoko |> Enum.take(5)
["ドコ ", "ドコ ", "ドコ ", "ズン ", "ドコ "]

Enum.takeの地点で実行されます。

kiyoshi

無限長のリストを引数に取り内部的にwordを最大5wordバッファします。
バッファ内容に対して [@zun,@zun,@zun,@zun,@doko]とマッチングしマッチしたらキ・ヨ・シ!をリストに挿入します。

 def kiyoshi(zundoko) do
    zundoko |> Stream.transform([], fn e, acc ->
      if Enum.count(acc) < 5 do
        {[e], [e|acc]}
      else 
        [_ | tail] = Enum.reverse(acc)
        next_acc = Enum.reverse(tail)
        case Enum.reverse(acc) do
          [@zun,@zun,@zun,@zun,@doko] -> {[@kiyoshi,e],[e | next_acc]}
          _ -> {[e],[e | next_acc]}
        end
      end        
    end)
  end

Stream.transform(enum, acc, fun)は以下のように引数を取ります。

  • enum Stream(遅延評価リスト)
  • acc(アキュームレータ) 処理全体を通して使用する一時保存変数です。今回はバッファとしてリストをもたせています
  • fun (element,acc) 第一引数は上述enumの各要素、第二引数に上述のアキュームレータが来ます。
    返却値としては返却するエレメントと次のアキュームレータの2要素のタプルとなります。