Part2 : ErlangVMで動くRuby風の関数型言語Elixir(エリクサー) : 基礎編
Part1はこちら
インターフェース
defprotocolでinterfaceのようなものが定義できる
defprotocol Checker do def ok?(data) end
defimplでinterfaceの実装を定義できる
defimpl Checker, for: List do def ok?([]), do: "ng" def ok?([h | _]) when h == 1, do: "ok" def ok?([2 | _]), do: "ok2" end defimpl Checker, for: Number do def ok?(1), do: "ok" def ok?(_), do: "ng" end Checker.ok?([1,2,3]) # ok Checker.ok?([2,3,4]) # ok2 Checker.ok?([3,4,5]) # ng Checker.ok?(1) # ok Checker.ok?(2) # ng
関数をキャプチャ
定義済みの関数を、別の関数に渡したいとき等に。
f = &Integer.odd?/1 Enum.map([1,2,3,4,5], f) # [true, false, true, false, true]
Erlangの関数をコール
:(コロン)をつけるとErlangのモジュールが呼べる。
:timer.sleep 1000 # 1秒sleep
プロセス生成
spawnで生成。receiveで外から値を受け取れる。
defmodule Process do def from do receive do i -> IO.inspect i * i after 100 -> IO.inspect "timeout.." end end end p = spawn Process, :from, [] p <- 2 # プロセスに値を送るとreceiveで受け取れる。
Stream
scalaにもある無限のリストを作るコレクション
IO.inspect Stream.map(1..1000000000, &(&1 * &1)) |> Enum.take(5) # [1, 4, 9, 16, 25]
File
ファイルをread。
case File.read("/etc/hosts") do { :ok, body } -> IO.inspect body { :error, reason } -> IO.inspect reason end
!を付けると例外を飛ばすようになる。rubyっぽい...
body = File.read!("/etc/hosts") IO.inspect body
例外をcatchしてみる
try do File.read! "/etc/hogeeeee" rescue File.Error -> IO.inspect "catche!" end
様々なファイル操作の関数がある
File.rm_rf! "/tmp/fuga" File.mkdir! "/tmp/fuga" File.write! "/tmp/fuga/elixir.txt", "elixir!" IO.puts File.read! "/tmp/fuga/elixir.txt" IO.inspect File.ls! "/tmp/fuga" File.rm! "/tmp/fuga/elixir.txt"
pmap
Elixir関係ないけど、便利なErlangの関数だったので。
1ループを1プロセスで実行するmap。ものすごい並列感...
defmodule Par do def exec(i) do :timer.sleep 1000 i * i end end :rpc.pmap {Par, :exec}, [], [1,2,3,4,5,6,7,8,9] # 1sかかる Enum.map [1,2,3,4,5,6,7,8,9], &Par.exec/1 # 9sかかる
公式サイトを翻訳したほうが早いんじゃないかと思えてきた...