0%

Elixir on Dockerで関数型言語をはじめよう - Part1: iExと文字列

先月ManningからElixir in Actionが出版されました。MEAPから積ん読だったのでそろそろ読み始めようと思います。最近はPhoenixというWebフレームワークも人気が出ています。Erlangがすっと入ってこなかったところと、Rubyで嫌いなところが、Elixirで書くとメインの開発言語として使えるのか楽しみです。Elixirはドキュメントサイトが充実していて読みやすいです。まずはGetting StartedからIntroductionが動く環境を用意します。

プロジェクト

適当なところにプロジェクトを作成してdocker-compose.ymlを用意します。

$ cd ~/elixir_apps
$ tree
.
└── docker-compose.yml

Dockerイメージはtrenpixster/elixirを使います。リポジトリは明記されていませんがたぶんこちら、trenpixster/elixir-dockerfileです。

~/elixir_apps/docker-compose.yml
elixir: &defaults
image: trenpixster/elixir
working_dir: /app
volumes:
- .:/app
entrypoint: ["elixir"]
elixirc:
<<: *defaults
entrypoint: ["elixirc"]
iex:
<<: *defaults
entrypoint: ["iex"]
bash:
<<: *defaults
entrypoint: ["bash"]

バージョンの確認

docker-compose.ymlに定義したbashサービスを実行してインストールしたパッケージのバージョンを確認します。

$ docker-compose run --rm bash

Erlang OTPのバージョンは17.5です。

$ cat /usr/lib/erlang/releases/17/OTP_VERSION
17.5

Elixirのバージョンは1.0.4です。

$ elixir -v
Elixir 1.0.4

erlはErlangのインタラクティブシェルです。バージョンは6.4です。

$ erl -version
Erlang (ASYNC_THREADS) (BEAM) emulator version 6.4

iEx

ElixirではiExという専用のインタラクティブシェルが使えます。docker-compose.ymlに定義したiexサービスを起動します。

$ docker-compose run --rm iex
Erlang/OTP 17 [erts-6.4] [source] [64-bit] [async-threads:10] [kernel-poll:false]

Interactive Elixir (1.0.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)>

Ctrl+C を押して、a、enterで終了します。

BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
(v)ersion (k)ill (D)b-tables (d)istribution

文字列

Getting Startedにあるサンプルを実行してみます。

iex(1)> 40 + 2
42
iex(2)> "helo" <> "world"
"heloworld"

<>は文字列結合演算子なので、2つ目の"helo" <> "world"は文字列の結合、またはバイナリの結合を表しています。Elixirの文字列にはダブルクォートで囲うバイナリのStringと、シングルクォートで囲うリストの文字リスト (Char list)があります。Binaries, strings and char listsの説明を読んでみます。

文字列 (String)

Elixirの文字列はUnicodeのコードポイントをUTF-8でエンコードしたバイト列です。コードポイントは整数値 (integer)です。リテラル表記はダブルクォートで囲みます。is_binaryでtrueが返るように、文字列はバイナリです。

iex(1)> string = "hello"
"hello"
iex(2)> is_binary string
true

のUnicodeのコードポイントは16進数で3042、10進数で12345です。1バイトは10進数で0から255までしか表現できません。1バイトでは表現しきれないため3バイトを使います。文字列に?を使うとUnicodeのコードポイントを出力できます。

iex(3)> ?あ
12354
iex(4)> byte_size "あ"
3

また、Elixirではバイナリを<<>>で表記します。バイナリは<<0,1>>のようなバイト列です。<>でバイナリを結合することができます。

iex(5)> <<0,1>> <> <<2,3>>
<<0, 1, 2, 3>>

文字列とヌルバイトの<<0>><>で結合すると、最初の文字列のバイナリ表記を出力できます。

iex(6)> "あ" <> <<0>>
<<227, 129, 130, 0>>

のバイト列は<<227,129,139>>になります。

iex(7)> <<227, 129, 130>>
"あ"

文字リスト (Char list)

文字をシングルクォートで囲うと文字のリストになります。

iex(1)> char_list = 'hello'
'hello'
iex(2)> is_list char_list
true

文字リストはUnicodeのコードポイントで構成されるリストです。

iex(2)> ''
[12354]
iex(3)> 'あい'
[12354, 12356]
iex(4)> to_char_list "あい"
[12354, 12356]

1バイトで表現できる文字の場合、文字リストを評価するとコードポイントでなく文字そのものが表示されます。

iex(4)> 'ab'
'ab'

Binaries, strings and char listsによると、文字リストはバイナリを引数に取れない古いErlangのライブラリで使われているようです。