Skip to content

Instantly share code, notes, and snippets.

@hakobe
Last active December 21, 2015 12:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakobe/6308609 to your computer and use it in GitHub Desktop.
Save hakobe/6308609 to your computer and use it in GitHub Desktop.

三分で学ぶErlang

Erlangて何?

  • 関数型 並行志向プログラミング言語とその環境
  • 分散環境/耐障害性/無停止動作
  • Ericssonでばりばり使われている

最近のはやり

  • Riak 分散型NoSQL
  • CouchDB 分散型NoSQL
  • logplex Herokuのfluentdみたいなやつ

GitHub を explore せよ

インストール

$ brew install erlang

起動

$ erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false] [dtrace]

Eshell V5.9.3.1  (abort with ^G)
1> % q(). で終了

変数

Num  = 100.  % 変数は大文字
Atom = atom. % 小文字はアトム(Rubyのシンボル)
  • 一度代入すると変更できない

関数

fact(0) -> 1;             % パターンの区切りはセミコロン
fact(N) -> N * fact(N-1). % 文末はピリオド
% 関数値 は fun() -> end
double(L) -> 
    lists:map( fun(N) -> N * 2 end, L ).

case とか リスト内包表記とか パターンマッチとか

fact2(N) ->
  case N of
    0 -> 1;
    N -> N * fact2(N-1)
  end.

double2(L) -> [2 * X || X <- L].

sum([])    -> 0;
sum([H|T]) -> H + sum(T).

ふつうの関数型言語

ふつうじゃないところ

言語内に独自のプロセスの概念

  • Actorモデル
P = spawn( fun () -> 
  % ここに別のプロセスで実行する処理を書く 
end ).
  • OSのプロセスと独立してVMがスケジューリング
  • 異なるプロセスはメッセージで協調
    • 共有メモリをつかわない
  • とても軽量。1000000 プロセスくらい作っても怒られない

プロセス間メッセージング

  • メッセージを使ってプロセスに指示を送ったり結果を受け取ったりする
Hello = spawn( fun() -> 
    receive % ここでブロックしてメッセージを待つ
        hello -> io:format("Hello, World!~n");
    end
end ).
> Hello ! hello.         % ! でメッセージ(hello)を送信
Hello, World!

> Hello ! hello.         % 一回receiveするとプロセスは死ぬ..

再帰呼び出しでloopさせる

-module(hello).
-export([start/0]).

start() ->
    spawn( fun() -> loop() end ).

loop() -> % loopという名前に特に意味は無い
    receive
        hello -> 
            io:format("Hello, World!~n"),
            loop(); % 何度もメッセージを受け付けられる
    end.
> Hello = hello:start(). % receiveがメッセージを待ってる
> Hello ! hello.         % ! でメッセージが送信できる
Hello, World!
> Hello ! hello.         % 何度も送れる
Hello, World!

loopに状態を持たせる

  • わんわんとなく犬プロセスに名前をつける
-module(dog).
-export([start/0]).

start() ->
    spawn( fun() -> loop("nanasi") end ).

loop(Name) ->
    receive 
        hi ->
            io:format("wanwan! I'm ~p~n", [Name]),
            loop(Name);
        {name, NewName} ->
            loop(NewName);
    end.
> D = dog:start().
> D ! hi
wanwan! I'm "nanasi"
> D ! {name, "hachi"}.
> D ! hi
wanwan! I'm "hachi"

実行中のコードを変更する

  • 動いている犬をあとからコンパイルした猫にすげかえる

Erlangスタイル

  • とりあえず処理ごとにプロセスを作ってloopする
    • オブジェクト指向言語でクラスのインスタンスを作るくらいの気楽さでプロセスを作る
  • メッセージで処理の依頼と結果の取得
  • 状態はloopの引数で保持
    • どのコードを動かすかも状態の1つ
  • OTPという汎用フレームワークでもこういう感じ

まとめ

  • 関数型プログラミング言語
  • プロセスで並行性をサポート = Actorモデル
  • 文法がきもい
    • 慣れれば気にならなくなってくる
    • Elixirもあるよ
  • 古いけど、今も勢いのあるプロダクトがあって学ぶ価値がある

参考文献

プログラミングErlang

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment