3
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-03-22

関数のキャプチャ

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

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
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4