モジュールと関数

■モジュール

モジュールは関数をまとめておくコンテナ(入れ物)です。
機能毎にモジュールを作成して、その中に機能に応じた関数を入れておくことで
様々なプロジェクトで使いまわすことができるので、
モジュールを上手く利用したらプロジェクトの開発効率を上げることができます。
IOやListなどはElixirが用意しているモジュールです。

●書式
	・書式例
		defmodule モジュール名 do
			この中に関数を書く
		end

	・具体例
		defmodule First do

		end

	上の具体例ではFirstという名前のモジュールを定義しました。

●使用方法
	モジュールの使用はモジュール内の関数を呼び出すことを基本としますので、
	「モジュール名.関数名」が一般的な使い方になります。

	・例
		IO.puts "Hello World"

	上の例ではIOモジュールのputs関数を使用してHello Wolrdと出力しました。

■関数

関数型言語の関数は入力からのみ出力が決定することを目指して作成します。
これは関数呼び出しで同じ値の引数を使用した場合、必ず同じ出力になるということで、
この法則に満たない関数は手続きと呼びます。

●関数定義
	関数を作成することを「関数定義」と呼びます。
	関数定義はモジュールの中で行う必要があります。

	・書式例
		def 関数名(引数) do
			処理内容
		end

	・具体例
		def print_str(str) do
			IO.puts "#{str}"
		end

●関数の呼び出し
	関数の呼び出しは「モジュール.関数名(引数)」で呼び出すことができます。
	関数を呼び出すと関数に引数が渡されて、定義した内容が実行されます。

	・書式例
		モジュール名.関数名(引数)

	・具体例
		defmodule TestModule do
			def print_str(str) do
				IO.puts "#{str}"
			end
		end

		TestModule.print_str("yttm-work")

		

●戻り値
	関数は実行結果を戻すことができます。
	※ElixirではJavaやC++などのreturnに相当する仕組みはありません。

	・例
		defmodule TestModule do
			def print_str(str) do
				"#{str}"
			end

			def add_sum(a, b) do
				a + b
			end
		end

		IO.puts TestModule.print_str("yttm-work")
		IO.puts TestModule.add_sum(1, 2)

●定義場所
	関数定義は基本的にモジュールの中に定義する必要があります。
	モジュール内で定義した場合エラーになります。

	・エラー例
		defmodule TestModule do
			def message(str \\ "default") do
				"#{str}"
			end
		end

		def test_function do
			IO.puts "Test"
		end

■アリティ(arity)

アリティとは関数の後ろに表示されている数字のことです。
Elixirでは関数の説明やエラーの際に「関数名/数値」が書かれますが、
これは設定している引数の数や必要な引数の数を表しています。

●例
	・コード
		defmodule TestModule do
			def print_str(str) do
				"#{str}"
			end
			
			def add_sum(a, b) do
				a + b
			end
		end

		IO.puts TestModule.add_sum(1)

	・エラー内容
		** (UndefinedFunctionError) function TestModule.add_sum/1 is
		   undefined or private. Did you mean one of:
				
			* add_sum/2

			TestModule.add_sum(1)

	上のエラーは引数1つのTestModule.add_sumは定義されてないから
	使えないという内容です。
	その下の「add_sum/2」はadd_sumは引数が二つ必要であることをヒントとして書かれています。

●アリティ毎の定義
	Elixirの関数は名前とアリティによって判断されるので、引数の数が違えば別の関数として扱われます。

	・例
		defmodule TestModule do
			def add_sum(a, b) do
				a + b
			end

			def add_sum(a, b, c) do
				a + b + c
			end
		end

		IO.puts TestModule.add_sum(1, 2)
		IO.puts TestModule.add_sum(3, 4, 5)

■デフォルト引数

関数の引数に初期値を設定することができます。
初期値を設定した引数は関数呼び出しで引数が設定されていない場合
設定した初期値が使用されます。

●例
	defmodule TestModule do
		def message(str \\ "default") do
			"#{str}"
		end
	end

	IO.puts TestModule.message("Hello")
	IO.puts TestModule.message

■プライベート関数

モジュールの外で使用してほしくない関数があった場合、アクセス制限を行うことができます。
アクセス制限をするとモジュール内でのみ使用できる関数になります。

●書式
	・書式例
		defp 関数名 do

		end

	・具体例
		defp private_funtion do
			
		end

■無名関数

無名関数(匿名関数)は関数として定義する規模ではないが関数として動作させた方が
効率が良いと判断した際に使用する簡易版の関数定義です。

●書式
	・書式例
		fn (引数) -> 内容 end

	・具体例
		f = fn (a, b) -> a + b end
		f.(1, 2)

	無名関数はfnと->の間に引数を設定し->とendの間に定義を行います。

●省略
	無名関数は「&」記号を使用することで更に短い形式に変更できます。

	・書式例
		&(処理内容)

	・具体例
		f = &(&1 + &2)
		f.(1, 2)

■プライベート関数

プライベート関数は他のモジュールからアクセスできない関数です。
属しているモジュール内部からのみ使用可能です。

●書式
	・書式例
		defp 関数名 do

		end

	・具体例
		defp add(a, b)
			a + b;
		end