75
第一回 Erlang 基礎勉強会 M.Ikuta ([email protected]) 2009/12/28 1 2010114日木曜日

Basic Study for Erlang #1

Embed Size (px)

Citation preview

第一回 Erlang 基礎勉強会

M.Ikuta ([email protected])2009/12/28

12010年1月14日木曜日

Erlang について実用的

ミドルウェアを作る為にある

並列、分散、耐障害

パターンマッチによるハンドリング(バイナリデータにも対応)

22010年1月14日木曜日

Erlang について実用的

ミドルウェアを作る為にある

OTP

Yaws, RabbitMQ, CouchDB, Kai, Scalaris, Ejabberd

32010年1月14日木曜日

Erlang について習得が容易

逐次処理

アクターモデル

42010年1月14日木曜日

Erlang 環境Erlang Shell

erl コマンドでノードとシェルを一つ起動

まずは、help().

もしくは、erl -man erlang

52010年1月14日木曜日

Erlang 環境Erlang Shell

シェルは、ノード上で動作するプロセスに過ぎない

62010年1月14日木曜日

Erlang 環境Erlang Shell

b(). 束縛された値の一覧

f(). 束縛された値を開放

f(X). 束縛された値Xを開放

72010年1月14日木曜日

Erlang 環境Erlang Shell

h(). 履歴

e(N). 履歴 N の式を実行

v(N). 履歴 N の式の値を取得

82010年1月14日木曜日

Erlang 環境Erlang Shell

i(). プロセスの一覧

i(X,Y,Z). プロセスの情報

pid(X,Y,Z). プロセスの ID

92010年1月14日木曜日

Erlang 環境Erlang Shell

c(F). コンパイル後にロード

l(M). モジュールロード

m(). ロード済モジュール一覧

m(M). モジュールの情報

102010年1月14日木曜日

Erlang 環境Erlang Shell

c,l,m と関係ある code

code:get_path().

code:add_patha().

code:add_pathz().

112010年1月14日木曜日

Erlang 環境Erlang Shell

ls().

cd().

memory().

q(). ノード停止

122010年1月14日木曜日

Erlang 環境JCL (Job Control Language)

一つのノード上で複数のシェルを起動し、適宜、切り替え

別ノードにリモートシェルで接続

Ctl-G で JCL モードへ移行

132010年1月14日木曜日

Erlang 環境JCL (Job Control Language)

h ヘルプ

j ジョブの一覧

c ジョブに接続

i ジョブの中断

142010年1月14日木曜日

Erlang 環境JCL (Job Control Language)

k ジョブの終了

s シェル起動

r リモートシェル起動

q ノードを終了

152010年1月14日木曜日

Erlang 環境erl コマンドのオプション

-man モジュールの man

-noshell ノードだけ起動

-s apply(M,F,[]). を評価

erl -noshell -s init stop

162010年1月14日木曜日

Erlang 環境erl コマンドのオプション

-eval 式を評価

-detached ノード起動後、すぐにデタッチ

OS 上に erl プロセスが残る

172010年1月14日木曜日

Erlang 環境erl コマンドのオプション

-sname ノード名を指定

ノード間通信に必要

@ 以降を省略すると `hostname -s` が使用される

182010年1月14日木曜日

Erlang 環境erl コマンドのオプション

-name ノード名を指定

@ 以降を省略すると `hostname` が使用される

192010年1月14日木曜日

Erlang 環境erl コマンドのオプション

-name ノード名を指定

-sname で起動したノードと通信できない

202010年1月14日木曜日

Erlang 環境erl コマンドのオプション

-remsh JCL の r と同じ

epmd が名前、ポート番号管理

.erlang.cookie, /etc/hosts, DNS など要確認

212010年1月14日木曜日

関数定義

sample/my_module.erl 参照

同名であってもパラメータの数(Arity)が異なるならば、別関数

222010年1月14日木曜日

関数パターンマッチ

sample/pattern_match.erl 参照

リストやタプルの分解ができる

Haskell と異なり k+1 は使えない

今回、バイナリは説明しない

232010年1月14日木曜日

関数パターンマッチ

‘;’ or と読む

‘,’ and と読む

‘.’ end と読む

242010年1月14日木曜日

関数ガード条件

sample/guard.erl 参照

関数は BIFs のみ使用可

パターンマッチの拡張であるため、副作用は NG (by 飛行機本)

252010年1月14日木曜日

関数ガード条件

sample/guard.erl 参照

関数は BIFs のみ使用可

BIFs は、erl -man erlang 参照

262010年1月14日木曜日

関数高階関数

関数を値として使用

関数を引数として渡す

> F1 = fun (X) -> X + 1 end.> F1(1).

> F2 = fun (F, X) -> F(X) end.> F2(F1, 2).

272010年1月14日木曜日

関数高階関数

関数を返す> F3 = fun (X) -> fun (Y) -> X+Y end end.> F4 = F3(1).> F4(1).> F5 = F3(10).> F5(1).

282010年1月14日木曜日

関数高階関数

無名関数は、ガードやパターンが使用できる(b(). で表示可能)> F6 = fun> (X) when is_integer(X) -> X;> (_X) -> 0> end.

292010年1月14日木曜日

リストリストとは何か?

ペアのペア

Erlang では [X | Y] でペアを表現

> [1, 2, 3] = [1 | [2 | [3 | []]]].

302010年1月14日木曜日

リストタプルとの違い

そもそもタプルとは?

タプル(Tuple) とは、2 つ組を表す Double、3 つ組を表す Triple のような組を表す英単語を一般化した言葉

312010年1月14日木曜日

リストタプルとの違い

そもそもタプルとは?

順序づけられた対象の並びを表すために用いられる

322010年1月14日木曜日

リストタプルとの違い

タプルを用いるべき箇所でリストを使わない

リストは、タプルより空間効率が悪い

332010年1月14日木曜日

リスト文字列の正体

実は、数値のリスト

R13B であれば、日本語も…

> "(A)" = [40,65,41].> “” = [].

> "日本語" =[26085,26412,35486].

342010年1月14日木曜日

リスト文字列の正体

文字列に対してリスト処理が可能

352010年1月14日木曜日

リスト連結

++ で行う

XS ++ [X] は、[X | XS] より遅い(ペアのペアだから、当たり前)

362010年1月14日木曜日

リスト差分

-- で行う> [2,4,1,2,3,4,5] = > [1,2,3,4,5,1,2,3,4,5] -- [1,3,5].

372010年1月14日木曜日

リスト内包表記

数学の内包表記は、ある集合から別の集合を生成

Erlang の内包表記は、あるリストから別のリストを生成

382010年1月14日木曜日

リスト内包表記

[X*X || X <- lists:seq(1, 5)].

X*X は構築子

式を記述可能(関数も使用可能)

392010年1月14日木曜日

リスト内包表記

[X*X || X <- lists:seq(1, 5)].

X <- lists:seq(1, 5) は生成器

値がリストなる式を記述

402010年1月14日木曜日

リスト内包表記

[X*X || X <- lists:seq(1, 5)].

X のスコープは、内包表記内

412010年1月14日木曜日

リスト内包表記

‘,’ で区切る事で、複数の生成器を列挙できる

得られるリストは、全ての要素の組み合わせ

> [{1,4},{1,5},{2,4},{2,5},{3,4},{3,5}] = > [{X, Y} || X <- [1,2,3], Y <- [4,5]].

422010年1月14日木曜日

リスト内包表記

生成器は、左から順に評価される

生成器にパターンマッチを使用

> [1,2,3,4,5] = > [X || XS <- [[1,2,3], [4,5]], X <-XS].

> [1] = [X || {X, a} <- [{1, a}, {2, b}]].

432010年1月14日木曜日

リスト内包表記

生成器の後ろにフィルタを記述

フィルタは、Bool 値を返す式> [1,3,5,7,9] = > [X || X <- lists:seq(1, 10),> X rem 2 =:= 1].

442010年1月14日木曜日

リスト内包表記

フィルタは、Bool 値を返す式> [1,3,5,7,9] = > [X || X <- lists:seq(1, 10),> X rem 2 =:= 1].

452010年1月14日木曜日

リスト内包表記

内包表記と無名関数で、素数を返す関数を記述

sample/prime.erl 参照

462010年1月14日木曜日

リスト再帰

再帰関数 = ある関数の中で、再びその自身を関数を評価する関数

472010年1月14日木曜日

リスト再帰

lists:sum/1 を定義するsum([], Acc) -> Acc;sum([X | XS], Acc) when is_number(X) -> sum(XS, X + Acc);sum([_X | XS], Acc) -> sum(XS, Acc).

482010年1月14日木曜日

リスト再帰

lists:sum/1 を定義するsum([], Acc) -> Acc;sum([X | XS], Acc) when is_number(X) -> sum(XS, X + Acc);sum([_X | XS], Acc) -> sum(XS, Acc).

累算器を使用

492010年1月14日木曜日

リスト再帰

lists:sum/1 を定義するsum([]) -> 0;sum([X | XS]) when is_number(X) -> X + sum(XS);sum([_X | XS]) -> sum(XS).

累算器を未使用

502010年1月14日木曜日

リスト再帰

lists:sum/1 を定義するsum([]) -> 0;sum([X | XS]) when is_number(X) -> X + sum(XS);sum([_X | XS]) -> sum(XS).

末尾再帰ではない

512010年1月14日木曜日

リスト再帰

Insert Sort を実装する

sample/isort.erl 参照の事

522010年1月14日木曜日

リスト再帰

考える順番(元ネタはプログラミング Haskell)

1.引数と返り値を決める2.場合分けをする3.簡単な方を定義する4.複雑な方を定義する5.最適化する

532010年1月14日木曜日

リスト再帰

考える順番

isort:insert/2 を例に考える

542010年1月14日木曜日

リスト再帰

考える順番

1.引数と返り値を決めるinsert(int(), [int()]) -> [int()]

552010年1月14日木曜日

リスト再帰

考える順番

2.場合分けをするinsert(X, []) -> ;insert(X, [Y | YS]) when X =< Y -> ;insert(X, [Y | YS]) -> .

562010年1月14日木曜日

リスト再帰

考える順番

3.簡単な方を定義するinsert(X, []) -> [X];insert(X, [Y | YS]) when X =< Y -> ;insert(X, [Y | YS]) -> .

572010年1月14日木曜日

リスト再帰

考える順番

3.簡単な方を定義する(続き)insert(X, []) -> [X];insert(X, [Y | YS]) when X =< Y -> [X | [Y | YS]];insert(X, [Y | YS]) -> .

582010年1月14日木曜日

リスト再帰

考える順番

4.複雑な方を定義するinsert(X, []) -> [X];insert(X, [Y | YS]) when X =< Y -> [X | [Y | YS]];insert(X, [Y | YS]) -> [Y | insert(X, YS)].

592010年1月14日木曜日

リスト再帰

考える順番

5.最適化するinsert(X, []) -> [X];insert(X, [Y | _YS]=XS) when X =< Y -> [X | XS];insert(X, [Y | YS]) -> [Y | insert(X, YS)].

602010年1月14日木曜日

リスト再帰

[課題]lists:seq/2 を定義する

sample/seq.erl 参照の事

612010年1月14日木曜日

リスト再帰

多重再帰

sample/qsort.erl 参照の事

末尾再帰ではない(スタックオーバフローの可能性あり)

622010年1月14日木曜日

リスト再帰

相互再帰

kai_tcp_server_acceptor

recv/5

call_mod/6

632010年1月14日木曜日

リストlists モジュール

リストを操作するための標準モジュール

erlang モジュール並によく使う(by 飛行機本)

642010年1月14日木曜日

リストlists モジュール

特に使用頻度の高い関数

lists:foreach/2 リストの各要素に関数を適用する

foreach(_F, []) -> ok;foreach(F, [X|XS]) -> F(X), foreach(F, XS).

652010年1月14日木曜日

リストlists モジュール

特に使用頻度の高い関数

lists:map/2 リストの各要素に関数を適用し、新しいリストを返す

map(F, XS) -> [F(X) || X <- XS].

662010年1月14日木曜日

リストlists モジュール

特に使用頻度の高い関数

lists:filter/2 リストから条件を満たす要素を取り出す

filter(F, XS) -> [X || X <- XS, F(X)].

672010年1月14日木曜日

リストlists モジュール

特に使用頻度の高い関数

lists:foldl/3 リストを左から畳む

[課題]lists:foldl/3 を定義する

[課題]lists:foldr/3 を定義する

682010年1月14日木曜日

リストlists モジュール

fold[lr] は、畳み込むというより、累算器を使う処理に使う

692010年1月14日木曜日

リストlists モジュール

fold[lr] は、畳み込むというより、累算器を使う処理に使う

revers(XS) -> lists:foldl( fun (X, ACC) -> [X|ACC] end, [], XS).

702010年1月14日木曜日

リストlists モジュール

fold[lr] は、畳み込むというより、累算器を使う処理に使う

map(F, XS) -> lists:foldl( fun (X, ACC) -> ACC ++ [F(X)] end, [], XS).

712010年1月14日木曜日

リストlists モジュール

fold[lr] は、畳み込むというより、累算器を使う処理に使う

map(F, XS) -> lists:reverse(lists:foldl( fun (X, ACC) -> [F(X)|ACC] end, [], XS)).

722010年1月14日木曜日

リストlists モジュール

fold[lr] は、畳み込むというより、累算器を使う処理に使う

[課題] lists:filter/2 を fold[lr] で定義する

732010年1月14日木曜日

以上、お疲れ様でした。

752010年1月14日木曜日