Elixir

Elixirチュートリアル 関数のキャプチャ

More than 1 year has passed since last update.


関数のキャプチャ

関数名/引数の数 で対象の関数を引っ張ってこれるらしい

iex> Math.zero?(0)

true
iex> fun = &Math.zero?/1
&Math.zero?/1
iex> is_function fun
true
iex> fun.(0)
true
iex> fun = &Math.zero?/2 # 関数がなくても引っ張ってこれることは来れる
iex> fun.(0,1) # でも呼び出すとめっちゃ怒られる。おこだよ!!!!
** (UndefinedFunctionError) undefined function Math.zero?/2
Math.zero?(0, 1)

is_function/1のような,ローカルな関数やインポートされた関数はモジュールをつけなくてもキャプチャできる

iex> &is_function/1

&:erlang.is_function/1
iex> (&is_function/1).(fun)
true

Ruby辺りと一緒で &1 は関数に渡された最初の引数を示す &(&1+1)fn x -> x + 1 end と同じ

iex> fun = &(&1 + 1)

#Function<6.71889879/1 in :erl_eval.expr/5>
iex> fun.(1)
2


デフォルト引数 - Default arguments

\\ でデフォの引数決められる

defmodule Concat do

def join(a, b, sep \\ " ") do
a <> sep <> b
end
end

IO.puts Concat.join("Hello", "world") #=> Hello world
IO.puts Concat.join("Hello", "world", "_") #=> Hello_world

デフォ値のみの関数を分けて設定しておくとわかりやすい

defmodule Concat do

def join(a, b \\ nil, sep \\ " ")

def join(a, b, _sep) when is_nil(b) do
a
end

def join(a, b, sep) do
a <> sep <> b
end
end

IO.puts Concat.join("Hello", "world") #=> Hello world
IO.puts Concat.join("Hello", "world", "_") #=> Hello_world
IO.puts Concat.join("Hello") #=> Hello

↓こういう描き方すると上にしか入らないから気をつけろって怒られる

defmodule Concat do

def join(a, b) do
IO.puts "***First join"
a <> b
end

def join(a, b, sep \\ " ") do
IO.puts "***Second join"
a <> sep <> b
end
end