Erlangをインストールするには

「7つの言語 7つの世界」第6章の学習のために、Erlang(アーラン)言語をインストールします。

RiakCouchDBErlangの名前がでてきたよ。

7つの言語 7つの世界

  • Ruby
  • Io
  • Prolog
  • Scala
  • Erlang
  • Cloijure
  • Haskell

書籍では、バージョン R13B02をインストールして、Eshell 5.4.13を使っているよ

Erlang公式サイト

Erlang Programming Language
Erlang Programming Language

最新は、Erlang/OTP 23.0

Windows 10では、Erlang/OTP 23
macOS 10.15.4では、Erlang/OTP 23
Ubuntu 18.04では、Erlang/OTP 20
書籍内のコードはひととおり動いたよ

Windows 10

https://www.erlang.org/downloads を表示して、Windows用インストーラのリンクをクリックしてダウンロードします。

インストーラを起動します。次のダイアログが表示されたら、「詳細情報」をクリックしてください。

「実行」ボタンをクリックしてください。

「この不明な発行元のアプリがデバイスに変更を加えようとしています」ダイアログが表示されたら、「OK」ボタンをクリックしてください。

インストーラが表示されました。「Next」ボタンをクリックしてください。

インストール先の場所です。変更しないで「Next」ボタンをクリックしてください。

スタートメニューの設定です。「Install」ボタンをクリックしてください。

インストールが開始されました。

途中、Visual C++のダイアログが表示されたら、「ライセンス条項および使用条件にに同意する」にチェックを付けて、「インストール」をクリックします。

PCを再起動して、あらためてインストーラを起動します。

インストールが完了しました。

コマンドプロンプトのerl

環境変数PATHに、C:\Program Files\erl-23.0.1\bin を追加します。筆者は学習用フォルダに env.bat を作りました。学習のたびにコマンドプロンプトを起動して、学習用フォルダにcdして、env.bat を実行することにしました。

:env.bat PATH=C:\Program Files\erl-23.0.1\bin;%PATH%
C:> cd study_7lang\erlang C:> env.bat

erlで起動します。Ctrl + C で終了します。Ctrl+ Gでは終了しませんでした。

C:> erl -version Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 11.0.1 C:> erl Eshell V11.0.1 (abort with ^G) 1> <-- Ctrl + C を押した C:>

コマンドプロンプトのwerl

コマンドプロンプト + erl の場合と同じように、env.bat を実行します。

C:> cd study_7lang\erlang C:> env.bat

werlコマンドで、Erlangウィンドウが起動します。

C:> werl C:>

Erlangウィンドウを終了するには、Fileメニュー、Exitです。

Eshell内で、Ctrl + Gを押して、q [Enter] でもErlangウィンドウが閉じます。

コマンドプロンプトから起動した場合、そのフォルダに translate.erl などのファイルを作り、Eshell で、c(translate). とコンパイルします。

スタートメニューのErlang

環境変数PATHの変更は不要です。

スタートメニューのErlangから起動しても、werlウィンドウが表示されます。この場合、作業フォルダーが C:\Program Files\erl-23.0.1\usr になってしまいます。このフォルダは読み込み専用なので、translate.erl などのファイルをここに作成できません。

そこで、エクスプローラで、スタートメニューのショートカット、C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Erlang OTP 23 (x64)\Erlang を表示します。右クリックでプロパティを表示して、作業フォルダ欄を学習用フォルダパスに変更してください。

macOS(Mac OS X) 10.15.4

homebrewでインストールします。

$ brew search erlang ==> Formulae erlang erlang@20 erlang@21 erlang@22
$ brew info erlang erlang: stable 23.0.2 (bottled), HEAD Programming language for highly scalable real-time systems
Erlang Programming Language
Erlang Programming Language
Not installed From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/erlang.rb ==> Dependencies Build: autoconf ✔, automake ✘, libtool ✔ Required: openssl@1.1 ✔, wxmac ✘ ==> Options --HEAD Install HEAD version ==> Caveats Man pages can be found in: /usr/local/opt/erlang/lib/erlang/man Access them with `erl -man`, or add this directory to MANPATH. ==> Analytics install: 23,838 (30 days), 88,466 (90 days), 375,810 (365 days) install-on-request: 5,993 (30 days), 22,505 (90 days), 91,694 (365 days) build-error: 0 (30 days)
$ brew install erlang $ which erl /usr/local/bin/erl

Erlang emulator version 11.0.2Erlang/OTP 23 でした。

$ erl -version Erlang (SMP,ASYNC_THREADS,HIPE) (BEAM) emulator version 11.0.2 $ erl Erlang/OTP 23 [erts-11.0.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace] Eshell V11.0.2 (abort with ^G) 1>

Ubuntu 18.04

aptでインストールします。

$ apt show erlang Package: erlang Version: 1:20.2.2+dfsg-1ubuntu2 Priority: optional Section: universe/interpreters Origin: Ubuntu Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com> Original-Maintainer: Debian Erlang Packagers <pkg-erlang-devel@lists.alioth.debian.org> Bugs: https://bugs.launchpad.net/ubuntu/+filebug Installed-Size: 51.2 kB Depends: erlang-base | erlang-base-hipe, erlang-dev, erlang-asn1, erlang-common-test, erlang-corba, erlang-crypto, erlang-debugger, erlang-dialyzer, erlang-diameter, erlang-edoc, erlang-eldap, erlang-erl-docgen, erlang-et, erlang-eunit, erlang-ic, erlang-inets, erlang-megaco, erlang-mnesia, erlang-observer, erlang-odbc, erlang-os-mon, erlang-parsetools, erlang-public-key, erlang-reltool, erlang-runtime-tools, erlang-snmp, erlang-ssh, erlang-ssl, erlang-syntax-tools, erlang-tools, erlang-wx, erlang-xmerl Recommends: erlang-jinterface, erlang-ic-java, erlang-mode, erlang-src, erlang-examples Suggests: erlang-manpages, erlang-doc Homepage: http://www.erlang.org/ Download-Size: 13.7 kB APT-Sources: http://jp.archive.ubuntu.com/ubuntu bionic/universe amd64 Packages Description: 並行、リアルタイム、分散関数型言語 Open Source Erlang は、エリクソンのコンピュータ科学研究所で設計された、関数型 プログラミング言語です。 . Some of Erlang main features are: * Clear declarative syntax and is largely free from side-effects; * Built-in support for real-time, concurrent and distributed programming; * Designed for development of robust and continuously operated programs; * Dynamic code replacement at runtime. . この Erlang の配布には、豊富なライブラリとアプリケーションを提供する OTP (Open Telecom Platform: オープンテレコムプラットフォーム) も含んでいます。 . このパッケージはダミーパッケージです。Erlang と OTP のランタイム、 アプリケーション、ソース、ソースコード例と Emacs 用の Erlang 編集モードを インストールします。 N: 追加レコードが 1 件あります。表示するには '-a' スイッチを付けてください。
$ sudo apt install erlang $ which erl /usr/bin/erl

Erlang emulator version 9.2Erlang/OTP 20 でした。

$ erl -version Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 9.2 $ erl Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false] Eshell V9.2 (abort with ^G) 1>

Eshellの終了方法

Eshellを終了するには、Ctrl + Gを押して、qを押します。

$ erl Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false] Eshell V9.2 (abort with ^G) 1> <-- Ctrl + Gを押した User switch command --> h c [nn] - connect to job i [nn] - interrupt job k [nn] - kill job j - list all jobs s [shell] - start local shell r [node [shell]] - start remote shell q - quit erlang ? | h - this message --> q $

もうひとつの方法は、Ctrl + Cを押して、aを押すことでも、Eshellを終了します。

$ erl Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [kernel-poll:false] Eshell V9.2 (abort with ^G) 1> <-- Ctrl + Cを押した BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution a $

セルフスタディ

筆者の解凍例をうのみにしないほうがいいわよ

1日目

・再帰を用いて文字列を構成する単語の数を返す関数を書け。

ヒントをください〜

文字列内の空白文字を数えたらどう?

文字列内の空白文字を数えることにします。簡単にするために、文字列の先頭や末尾に空白文字はない、単語区切りの空白文字は1文字とし、2文字以上連続しない、とします。

文字列単語数
""0
"hello"1
"hello world"2
%% wc.erl -module(wc). -export([wc/1]). is_space(32) -> 1; is_space(_) -> 0. wc_body("") -> 0; wc_body([Head|Tail]) -> is_space(Head) + wc_body(Tail). wc("") -> 0; wc(Anything) -> wc_body(Anything ++ " ").
1> c(wc). {ok,wc} 2> wc:wc(""). 0 3> wc:wc("hello"). 1 4> wc:wc("hello world"). 2

・再帰を用いて10まで数える関数を書け。

「数える」のヒントをください〜

1, 2, 3 と表示してみたら?

まず、10, 9, 8, 7, 6, 5, 4, 3, 2, 1 と表示するものです。

%% count_down.erl -module(count_down). -export([count/1]). count(1) -> io:format("~p~n", [1]); count(N) -> io:format("~p~n", [N]), count(N-1).
23> c(count_down). {ok,count_down} 24> count_down:count(10). 10 9 8 7 6 5 4 3 2 1 ok

次に、1, 2, 3, 4, 5, 6, 7, 8, 9, 10 と表示するものです。

-module(count_up). -export([count/1]). count(N) -> count_up_to(1, N). count_up_to(M, N) when M =:= N -> io:format("~p ~n", [M]); count_up_to(M, N) -> io:format("~p ~n", [M]), count_up_to(M + 1, N).
28> c(count_up). {ok,count_up} 29> count_up:count(10). 1 2 3 4 5 6 7 8 9 10 ok

・{error, Message} または success という形式の入力が与えられたとき、マッチングを用いて、"success" または "error: message" のどちらかを出力する関数を書け。

%% print_result.erl -module(print_result). -export([print_result/1]). print_result(success) -> io:format("success~n"); print_result({error, Message}) -> io:format("error: ~p~n", [Message]).
39> c(print_result). {ok,print_result} 40> print_result:print_result(success). success ok 41> print_result:print_result({error, "Hoge"}). error: "Hoge" ok

2日目

• [{erlang, "a functional language"}, {ruby, "an OO language"}]
のようなキーワード値タプルのリストを考える. リストとキーワードを受け取り,そ
のキーワードに対応する値を返す関数を書け.

> List = [{erlang, "a functional language"}, {ruby, "an OO language"}].
としたとき、

> selfstudy2_1:map_get(erlang, List).
"a functional language"

> selfstudy2_1:map_get(ruby, List).
"an OO language"


となるような関数を作ります。

リストのHead|Tailを使ったバージョン。

Head|Tailで考えようとすると、頭がねじれる感じがするよ。

-module(selfstudy2_1). -export([map_get/2]). -export([test/0]). map_get(Key, [{Key,Value}|_]) -> Value; map_get(Key, [_|Tail]) -> map_get(Key, Tail); map_get(_, _) -> not_found. assert(BoolExpr, Comment) -> case BoolExpr of true -> true; _ -> io:format("assert failed: ~p~n", [Comment]) end. test() -> List = [{erlang, "a functional language"}, {ruby, "an OO language"}], assert(map_get(erlang, List) =:= "a functional language", "#1"), assert(map_get(ruby, List) =:= "an OO language", "#2"), assert(map_get(scala, List) =:= not_found, "#3").

リスト内包表記を使ったバージョン。他の言語のfilterとmapに相当します。

リスト内包表記はすぐに思いつかないよ

-module(selfstudy2_1). -export([map_get/2]). -export([test/0]). map_get(Key, List) -> ValueList = [ V || { K, V } <- List, K == Key ], val_get(ValueList). val_get([]) -> not_found; val_get([Value]) -> Value. assert(BoolExpr, Comment) -> case BoolExpr of true -> true; _ -> io:format("assert failed: ~p~n", [Comment]) end. test() -> List = [{erlang, "a functional language"}, {ruby, "an OO language"}], assert(map_get(erlang, List) =:= "a functional language", "#1"), assert(map_get(ruby, List) =:= "an OO language", "#2"), assert(map_get(scala, List) =:= not_found, "#3").
12> List = [{erlang, "a functional language"}, {ruby, "an OO language"}]. [{erlang,"a functional language"},{ruby,"an OO language"}] 13> c(selfstudy2_1). {ok,selfstudy2_1} 14> selfstudy2_1:map_get(List, erlang). "a functional language" 15> selfstudy2_1:map_get(List, ruby). "an OO language" 16> selfstudy2_1:map_get(List, scala). []

•[{item quantity price}, …] という形式の買い物リストを考える.このとき, [{item total_price}, …] という形式の items のリストを構築するリスト内包表記を書け.ただし, total_price は, quantity×price とする.

> List = [{pencil, 4, 0.25}, {pen, 1, 1.20}, {paper, 2, 0.20}].
としたとき、

> xx:xx(List).
[{pencil,1.0},{pen,1.2},{paper,0.4}]

となるような関数を作ります。

-module(selfstudy2_2). -export([total_price/1]). %% > List = [{pencil, 4, 0.25}, {pen, 1, 1.20}, {paper, 2, 0.20}]. %% > selfstudy2_2:total_price(List). %% > [{pencil, 1.0}, {pen, 1.20}, {paper, 0.4}] total_price(List) -> [{Item, Quantity * Price} || {Item, Quantity, Price} <- List].
1> List = [{pencil, 4, 0.25}, {pen, 1, 1.20}, {paper, 2, 0.20}]. [{pencil,4,0.25},{pen,1,1.2},{paper,2,0.2}] 2> c(selfstudy2_2). {ok,selfstudy2_2} 3> selfstudy2_2:total_price(List). [{pencil,1.0},{pen,1.2},{paper,0.4}]

• 長さ 9 のリストまたはタプルとして表現された三目並べのボードを読み込むプロ
グラムを書け.勝者が確定している場合はその勝者( x または o のどちらか)を,
これ以上指し手がない場合は cat を,勝負がついていない場合は no_winner を返
すようにせよ.

何も置いていないセルを b、片方の指し手を x、もう片方の指し手を o としました。ボードは、要素が9個あるタプルにしました。

testは通るけど、他にいい方法があるわね

-module(selfstudy2_3). -export([judge/1]). -export([test/0]). -export([test_is_blank/0]). -export([test_count_blank/0]). -export([test_is_full/0]). -export([test_find/0]). -export([test_judge/0]). assert(BoolExpr) -> assert(BoolExpr, ""). assert(BoolExpr, Comment) -> case BoolExpr of true -> true; _ -> io:format("assert failed: ~p~n", [Comment]) end. judge({C11, C12, C13, C21, C22, C23, C31, C32, C33}) -> List1 = [{C11, C12, C13}, {C21, C22, C23}, {C31, C32, C33}, {C11, C21, C31}, {C12, C22, C32}, {C13, C23, C33}, {C11, C22, C33}, {C13, C22, C31}], List2 = [C11, C12, C13, C21, C22, C23, C31, C32, C33], WonByX = won_by_x(List1), WonByO = won_by_o(List1), IsFull = is_full(List2), if WonByX -> x; WonByO -> o; IsFull -> cat; true -> no_winner end. won_by_x(List) -> find({x, x, x}, List). won_by_o(List) -> find({o, o, o}, List). find(_, []) -> false; find(Item, [Item|_]) -> true; find(Item, [_|Tail]) -> find(Item, Tail). is_full(List) -> count_blank(List) =:= 0. count_blank([]) -> 0; count_blank([Head|Tail]) -> is_blank(Head) + count_blank(Tail). is_blank(b) -> 1; is_blank(_) -> 0. test() -> test_is_blank(), test_count_blank(), test_is_full(), test_find(), test_judge(). test_is_blank() -> assert(is_blank(b) =:= 1, "is_blank(b)"), assert(is_blank(x) =:= 0, "is_blank(x)"), assert(is_blank(o) =:= 0, "is_blank(o)"). test_count_blank() -> assert(count_blank([]) =:= 0, "count_blank #1"), assert(count_blank([x,x,x,x,x,x,x,x,x]) =:= 0, "count_blank #2"), assert(count_blank([x,x,x,x,x,x,x,x,b]) =:= 1, "count_blank #3"), assert(count_blank([b,b,b,b,b,b,b,b,b]) =:= 9, "count_blank #4"). test_is_full() -> assert(is_full([x,x,x,x,o,o,o,o,x]) =:= true, "test_is_full #1"), assert(is_full([x,x,x,x,o,o,o,o,b]) =:= false, "test_is_full #2"), assert(is_full([b,b,b,b,b,b,b,b,b]) =:= false, "test_is_full #3"). test_find() -> assert(find({x,x,x}, []) =:= false, "test_find #1"), assert(find({x,x,x}, [{x,x,x}]) =:= true, "test_find #2"), assert(find({x,x,x}, [{o,x,o},{x,x,x}] ) =:= true, "test_find #3"), assert(find({o,o,o}, [{o,x,o},{o,o,o}] ) =:= true, "test_find #4"). test_judge() -> assert(judge({x, x, x, b, b, b, b, b, b}) =:= x, "test_judge x"), assert(judge({o, o, o, x, b, b, x, b, b}) =:= o, "test_judge o"), assert(judge({o, x, x, x, o, o, x, o, x}) =:= cat, "test_judge cat"), assert(judge({o, o, x, x, b, b, x, b, b}) =:= no_winner, "test_judge no_winner").
1> c(selfstudy2_3). {ok,selfstudy2_3} 2> selfstudy2_3:test(). true 3> selfstudy2_3:judge({x, o, b, x, o, b, x, b, b}). x

3日目

この本の内容だけでは作れなかったよ

• translate_service を監視し,死んだら再起動するようにせよ.

• Doctor プロセスが死んだとき,自分自身で再起動するようにしてみよ.

• Doctor モニタのモニタを作成し,どちらかのモニタが死んだら再起動するようにせよ.

• メッセージのログをファイルに記録する基本的な OTP サーバを作成せよ.

• ネットワーク越しに動作するように translate_service を改良してみよ.

ここに解答例があったわ

2011-10-06
passingloopの日記

参考サイト

Erlangユーザーズガイド — Erlang User's Guide v5.8.1 documentation
Erlangのインストール(Windows編) / Erlang World
WindowsへのErlangのインストール方法

おすすめ書籍

Joe Armstrong (著) オーム社 2008/2
Francesco Cesarini (著), Simon Thompson (著) オライリージャパン 2010/7
柏原 正三(著) アスキー 2007
タイトルとURLをコピーしました