<Enjoy-Elixir>拡張子ex,exs
Enjoy-Elixirと称する、プログラミング言語Elixirを勉強する記事群の1つです。
Elixirコードファイルの拡張子
Elixir
のコードファイルに使う拡張子は慣習的に次の2つです。
ex
exs
この記事では2つの拡張子の使い分けについて説明します。
拡張子ex
拡張子 ex
は、コンパイルを目的としたコードファイルに使います。
動的型付けのプログラミング言語というと、コンパイルなしで動作するインタプリタ方式のものが多いですが、Elixirは動的型付け言語、かつ、 コンパイラ方式 の言語です。
Elixirは仮想マシンで動作します。これは、Elixirのコードファイルは、仮想マシンが解釈できるバイトコードに変換されて動作する、ということ。そのため、Elixirのコードファイルはコンパイルされる必要があります。
簡単な例を見てみましょう。
defmodule Hello do
def say(word) do
IO.puts("Hello, #{String.capitalize(word)}!")
end
end
Hello.say("world")
モジュール Hello
を定義し、その中で関数 say
を定義しています。モジュール Hello
の外側で、定義した say
関数を呼び出しています。
このコードファイルをコンパイルしてみます。コンパイルには elixirc
コマンドを使います。
$ elixirc hello.ex
Hello, World!
コンパイルと同時に、Hello.say("world")
の実行結果が出力されますね。
コンパイルが成功すると、コンパイル結果のバイトコードファイルも生成されます。
$ ls -1
Elixir.Hello.beam
hello.ex
Elixir.Hello.beam
という beam
拡張子のついたファイルがコンパイル結果のバイトコードファイルです。
Elixir.#{モジュール名}.beam
というのがバイトコードファイル名の規則です。
中身を見てみましょうか。
FOR1 tBEAMAtU8 Û Elixir.Hello__info__
attributescompile
deprecatedexports_md5 functionsmacrosmd5moduleerlangget_module_infosay
Elixir.String
capitalizeElixir.String.Chars to_string byte_sizeall Elixir.IOputsmodule_info Code Ò ¬ " ;2uBuRebUrEeu¢50@@@G P@G`@p@@N Ò¬ @5¥@=µ ¬ °|0om \p Z
\p@@À
Ð@NPà
こんな感じです。まあ、バイトコードなので基本的に中身は人間が読めるものではありません。(幽かに読めそうな雰囲気もあるかなきか。。。)
1つ実験をしてみましょう。次のコードファイルをコンパイルしてみます。
hello = fn word -> IO.puts "Hello, #{String.capitalize(word)}!" end
hello.("world")
モジュールを定義せずにインラインで(無名)関数を定義し、実行しています。処理自体は最初のモジュール Hello
のバージョンと変わりはありません。
このコードファイルをコンパイルします。
$ elixirc hello2.ex
Hello, World!
関数の処理は出力されましたね。では、バイトコードファイルは出力されているでしょうか?
$ ls -1
hello2.ex
上記の通り、バイトコードファイルは生成されていません。
次のことがわかりました。
- モジュールが定義されていなければバイトコードファイルは生成されない
コンパイルしてバイトコードファイルを生成するには、モジュールを定義しなければいけない、と言い換えることもできます。
コードファイルの拡張子を ex
にすることは、次の意味があります。
- コードファイルをコンパイルしてバイトコードを生成したい、という意思表示である。
ちなみにコンパイルするためのコードファイルの拡張子を ex
にするのは、あくまでも慣習 です。たとえば拡張子を hoge
など別のものにしても、モジュールが定義されていればコンパイルすることができます。
$ elixirc hello.hoge
Hello, World!
$ ls -1
Elixir.Hello.beam
hello.hoge
(だからといって特別な理由もなく、わざわざ慣習を破る必要はありませんけどね)
拡張子exs
拡張子 exs
の s
は script の s
です。
コードファイルに拡張子 exs
をつける場合は、 バイトコードの出力を目的にしない ことを意味します。
スクリプトモード
とも呼ばれますが、コードファイルの中の処理が実行されて、バイトコードを出力せずに処理を終えます。
スクリプトモード
での実行は、 elixir
コマンドを使います。
# goodbye.exs
defmodule Goodbye do
def say(word) do
IO.puts("Goodbye, #{String.capitalize(word)}!")
end
end
Goodbye.say("world")
実行してみましょう。
$ elixir goodbye.exs
Goodbye, World!
バイトコードファイルは出力されません。
$ ls -1
goodbye.exs
Elixir.Goodbye.beam
はありませんね。
elixir
コマンドの動きについて、少し詳しく説明します。
elixir
コマンドを実行したとき、バイトコードファイルは出力されませんが、バイトコード
自体は生成されて仮想マシンのメモリ上に展開されます。仮想マシンは展開されたバイトコードを実行して、結果を出します。しかし、 繰り返しますが、 バイトコードファイル
は出力しません。
拡張子 exs
のコードファイルを使う主な用途はテストです。テストコードのバイトコードファイルは本番運用のサービスには必要ないので、出力されなくていいわけです。
拡張子 ex
の場合と同じですが、 exs
もあくまで慣習です。だから、拡張子が exs
だからといってバイトコードファイルが作成できないわけではありません。
# elixirc コマンドを使うと `exs` のコードファイルでもバイトコードを生成できる
$ elixirc goodbye.exs
Goodbye, World!
$ ls -1
Elixir.Goodbye.beam
goodbye.exs
拡張子 ex
, exs
は、コードを書く人間がコードファイルをどのような目的で書いたのは意思表示するもの、と考えるとよいでしょう。
まとめ
この記事の内容をまとめます。
- 拡張子を
ex
にするかexs
にするかは、目的で分ける。 - 張子を
ex
にするのは、バイトコードファイルを生成するのが目的のコードファイル。 - ただし、バイトコードを生成できるのはモジュール定義のあるコードファイルである(つまり、
ex
をつけるということは必然的にモジュールが定義されているということを意味する)。 - 拡張子
exs
はスクリプト用途。バイトコードファイルは生成しない。 - テストコードには
exs
を使う。テストコードのバイトコードファイルは必要がないため。
以上です。