関数のキャプチャ
関数名/引数の数 で対象の関数を引っ張ってこれるらしい
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