Elixirは動的型付け言語です。つまり、変数の型がチェックされるのは実行時だけです。マッチ演算子の=を使うと、どんな型の値でも変数名に束縛できます。
# Bound an integer value of 1
count = 1
# You may re-bind variables
count = 2
# You may re-bind any type to a variable
count = false
# Strings can be created by enclosing characters within double quotes
message = "Success!"
Elixirは関数型プログラミング言語であり、名前のある関数はすべて_モジュール_の中で定義する必要があります。モジュールを定義するにはdefmoduleキーワードを使います。すべてのモジュールは実行時に他のすべてのモジュールから利用でき、プログラムの他の部分から見えるようにするための_アクセス修飾子_は必要ありません。_モジュール_は、他のプログラミング言語でいう_クラス_に似ています。
defmodule Calculator do
# ...
end
_名前付き関数_はモジュールの中で定義する必要があります。_公開_の名前付き関数を定義するにはdefキーワードを使います。
関数は0個以上の引数を取ることができます。関数内の最後の式の値は、常に_暗黙的に返されます_。
defmodule Calculator do
def add(x, y) do
x + y
end
end
関数を呼び出すには、そのモジュール名と関数名を指定し、関数の引数それぞれに値を渡します。
sum = Calculator.add(1, 2)
# => 3
defの代わりにdefpキーワードを使うと、_非公開_の関数を定義できます。非公開関数は、それを定義した同じモジュールの中からしか使えません。
定義されているのと同じモジュールの中で関数を呼び出すときは、モジュール名を省略できます。
短い関数は、1行の構文で書くこともできます(キーワードdoの前後にあるカンマ,とコロン:に注目してください)。
defmodule Calculator do
def subtract(x, y) do
private_subtract(x, y)
end
defp private_subtract(x, y), do: x - y
end
difference = Calculator.subtract(7, 2)
# => 5
difference = Calculator.private_subtract(7, 2)
# => ** (UndefinedFunctionError) function Calculator.private_subtract/2 is undefined or private
# Calculator.private_subtract(7, 2)
関数のことは、その_アリティ_で呼ぶことがよくあります。関数の_アリティ_とは、その関数が受け取る引数の数のことです。
# add/3 because this function has three arguments, thus an arity of 3
def add(x, y, z) do
x + y + z
end
モジュール名にはPascalCaseを使います。モジュール名は大文字のA-Zで始まる必要があり、文字a-zA-Z、数字0-9、アンダースコア_を含めることができます。
変数名と関数名にはsnake_caseを使います。変数名または関数名は小文字のa-zかアンダースコア_で始まる必要があり、文字a-zA-Z、数字0-9、アンダースコア_を含めることができ、疑問符?や感嘆符!で終わることがあります。
Elixirには、非常に充実していてドキュメントも整った標準ライブラリがあります。ドキュメントはhexdocs.pm/elixirでオンラインで読めます。このリンクはどこかに保存しておきましょう。これから何度も使うことになります!
ほとんどの組み込みデータ型には、そのデータ型を扱う関数を提供する対応するモジュールがあります。たとえば、整数にはIntegerモジュール、文字列にはStringモジュール、リストにはListモジュールなどがあります。
注目すべきモジュールの1つがKernelモジュールです。これは、算術演算子や制御フローのマクロなど、標準ライブラリの残りの部分がその上に成り立っている基本的な機能を提供します。Kernelモジュールの関数は自動的にインポートされるので、Kernel.という接頭辞を付けずに使えます。
コメントは、ソースコードを読む他のエンジニアへのメモとして使えます。Elixirでは、1行コメントの前に#を付けます。
この演習では、お気に入りの料理本をもとに、絶品のラザニアを作るためのコードを書いていきます。
タスクは5つあり、どれもラザニアの調理にかかる時間に関するものです。
引数を取らず、ラザニアをオーブンに入れておくべき時間を分で返すLasagna.expected_minutes_in_oven/0関数を定義します。料理本によると、オーブンでの予想時間は40分です。
Lasagna.expected_minutes_in_oven()
# => 40
Lasagna.remaining_minutes_in_oven/1関数を定義します。この関数は、ラザニアをオーブンに入れてからの実際の経過時間を引数に取り、前のタスクで定義したオーブンでの予想時間をもとに、ラザニアをあと何分オーブンに入れておく必要があるかを返します。
Lasagna.remaining_minutes_in_oven(30)
# => 10
Lasagna.preparation_time_in_minutes/1関数を定義します。この関数は、ラザニアに追加した層の数を引数に取り、1層あたり2分かかると仮定して、ラザニアの下準備にかかった時間を分で返します。
Lasagna.preparation_time_in_minutes(2)
# => 4
Lasagna.total_time_in_minutes/2関数を定義します。この関数は2つの引数を取ります。1つ目の引数はラザニアに追加した層の数、2つ目の引数はラザニアをオーブンに入れてからの経過時間(分)です。この関数は、ラザニアの調理に合計で何分かかったかを返します。これは、下準備にかかった時間と、その時点までにラザニアがオーブンにあった時間の合計です。
Lasagna.total_time_in_minutes(3, 20)
# => 26
引数を取らず、ラザニアが食べごろになったことを知らせるメッセージを返すLasagna.alarm/0関数を定義します。
Lasagna.alarm()
# => "Ding!"