Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?

More than 1 year has passed since last update.

@piacerex

ElixirのStreamでカウンタ付き無限ループ

fukuoka.ex代表のpiacereです
今回もご覧いただいて、ありがとうございます:bow:

Elixirでdefと末尾再帰を使った、スタンダードなカウンタ付き無限ループのコラムを見たら、Streamでカウンタ付き無限ループを書きたくなったので、書いてみました:yum:

そういえば、こないだのStream版ズンドコキヨシと言い、ややStream芸人になりつつある…:sweat:


:stars::stars::stars: お知らせ:Elixirもくもく会(リモート参加OK、入門トラック有)を今月末に開催します :stars::stars::stars:

「fukuoka.ex#14:Elixir/Phoenixもくもく会~入門もあるよ」を9/28(金)に開催します

今回から「Zoomによるリモート参加」を正式に受け付けるようになりましたので、福岡以外の都心や地方からでも参加できます(申し込みいただいたら、追ってZoom URLをconnpassメールでお送りします)

また、これまではElixir/Phoenix経験者を対象とした、もくもく会オンリーでしたが、今回から、入門者トラックも併設し、fukuoka.exアドバイザーズ/キャストに質問できるようにアップグレードしました

お申込みはコチラから
https://fukuokaex.connpass.com/event/100659/
image.png

Streamでカウンタ付き無限ループ

Streamでカウンタ付き無限ループを実装するには、Stream.iterateが便利

start = 0
count_up = 1
sleep_msec = 1000

Stream.iterate( start, &( &1 + count_up ) ) |> 
Enum.map( fn count -> 
  IO.puts( "count => #{ count }, count_up => #{ count_up }" )
  :timer.sleep( sleep_msec )
end )

ね?けっこうカンタンに組めるでしょ?

iexで上記を実行しても良いし、defで関数化してもOK

実行すると、こんな感じで、カウンタ付きの無限ループとなる(Ctrl+cでストップすると、iex毎、抜けてしまうが、止め方がそれしか無い)

count => 0, count_up => 1
(1秒待つ)
count => 1, count_up => 1
(1秒待つ)
count => 2, count_up => 1
(1秒待つ)
count => 3, count_up => 1
(1秒待つ)
…

カウンタ付き無限ループで、iexもどきを作る

IO.getsを併用すると、ユーザ入力待ちループも作れるので、iexのようなものを作ることもできる

start = 1
count_up = 1

Stream.iterate( start, &( &1 + count_up ) ) |> 
Enum.map( fn count -> 
  input = IO.gets( "iex(#{ count })> " )
  IO.write( "none exec #{ input }" )
end )

実行すると、見た目はiexそっくりだけど、何もしない役立たずが動く:stuck_out_tongue_winking_eye:

iex(1)> IO.puts( "hello" )
none exec IO.puts( "hello" )
iex(2)> IO.inspect( %{ "key1" => "v1", "key2" => "v2" } )
none exec IO.inspect( %{ "key1" => "v1", "key2" => "v2" } )
iex(3)>

ここまで来ておいて折角なので、Elixirコードを解釈できるようにしてみた:laughing:

start = 1
count_up = 1

Stream.iterate( start, &( &1 + count_up ) ) |> 
Enum.map( fn count -> 
  input = IO.gets( "iex(#{ count })> " )
  Code.eval_string( input )
end )

まるでiexのように、Elixirコード断片を実行できて、ちょっとだけ役立たずでは無くなる

iex(1)> IO.puts( "hello" )
hello
iex(2)> IO.inspect( %{ "key1" => "v1", "key2" => "v2" } )
%{"key1" => "v1", "key2" => "v2"}
iex(3)> [ 1, 2, 3 ] |> Enum.map( &( &1 + 1 ) ) |> IO.inspect
[2, 3, 4]

ちなみに、エラーになるようなコードを書くと、無限ループは終了し、元のiexに戻ってくる(全く同じ表示なので、戻ったか一瞬分からず、とても紛らわしい)

p.s.「いいね」よろしくお願いします

よろしければ、ページ左上の image.pngimage.png のクリックをお願いしますー:bow:

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
9
Help us understand the problem. What is going on with this article?