サーチ…


匿名関数

Elixirでは、一般的な慣行として、匿名関数を使用します。無名関数の作成は簡単です:

iex(1)> my_func = fn x -> x * 2 end
#Function<6.52032458/1 in :erl_eval.expr/5>

一般的な構文は次のとおりです。

fn args -> output end

読みやすくするために、引数の前後にかっこを入れることができます:

iex(2)> my_func = fn (x, y) -> x*y end
#Function<12.52032458/2 in :erl_eval.expr/5>

無名関数を呼び出すには、割り当てられた名前で呼び出して追加し.名前と引数の間に

iex(3)>my_func.(7, 5)
35

引数なしで匿名関数を宣言することは可能です:

iex(4)> my_func2 = fn -> IO.puts "hello there" end
iex(5)> my_func2.()
hello there
:ok

キャプチャ演算子の使用

匿名関数をより簡潔にするために、 キャプチャ演算子 &使用することができます。たとえば、次の代わりに:

iex(5)> my_func = fn (x) -> x*x*x end

あなたは書ける:

iex(6)> my_func = &(&1*&1*&1)

複数のパラメータを使用する場合は、各引数に対応する数値を1から数えて使用します。

iex(7)> my_func = fn (x, y) -> x + y end

iex(8)> my_func = &(&1 + &2)   # &1 stands for x and &2 stands for y

iex(9)> my_func.(4, 5)
9

複数の団体

無名関数は、( パターンマッチングの結果として)複数のボディを持つこともできます:

my_func = fn
  param1 -> do_this
  param2 -> do_that
end

複数のボディを持つ関数を呼び出すときElixirは、提供したパラメータを適切な関数本体と照合しようとします。

関数リストとしてのキーワードリスト

複数のKey-Valueペアを含む 'options'形式のパラメータにキーワードリストを使用する:

def myfunc(arg1, opts \\ []) do
  # Function body
end

上記の関数を以下のように呼び出すことができます:

iex> myfunc "hello", pizza: true, soda: false

これは以下と同等です:

iex> myfunc("hello", [pizza: true, soda: false])

引数の値は、それぞれopts.pizzaおよびopts.sodaとして使用できます。
あるいは、atoms: opts[:pizza]opts[:soda]使用することもできます。

名前付き関数とプライベート関数

名前付き関数

defmodule Math do
    # one way
    def add(a, b) do
        a + b
    end

    # another way
    def subtract(a, b), do: a - b
end

iex> Math.add(2, 3)
5
:ok
iex> Math.subtract(5, 2)
3
:ok

プライベート関数

defmodule Math do
    def sum(a, b) do
        add(a, b)
    end

    # Private Function
    defp add(a, b) do
        a + b
    end
end

iex> Math.add(2, 3)
** (UndefinedFunctionError) undefined function Math.add/2
Math.add(3, 4)
iex> Math.sum(2, 3)
5

パターンマッチング

Elixirは、引数の値に基づいて本体の関数呼び出しを照合します。

defmodule Math do
    def factorial(0): do: 1
    def factorial(n): do: n * factorial(n - 1)
end

ここで、正数の階乗は第2節と一致し、 factorial(0)は最初の節と一致します。 (単純化のために負の数を無視する)。 Elixirは上から下に関数をマッチさせようとします。 2番目の関数が1番目の関数の上に書かれている場合、無限の再帰に行くので予期せぬ結果になります。 factorial(0)factorial(n)一致するので、

ガード句

ガード句を使用すると、関数を実行する前に引数をチェックできます。ガード句は、通常、読みやすさのためにifcondより優先され、コンパイラにとって特定の最適化手法を容易にします。すべてのガードが一致する最初の関数定義が実行されます。

ガードとパターンマッチングを使用した階乗関数の実装例を次に示します。

defmodule Math do
    def factorial(0), do: 1
    def factorial(n) when n > 0: do: n * factorial(n - 1)
end

最初のパターンは、引数が0場合にのみ一致し0 。引数が0でなければ、パターンの一致は失敗し、次の次の関数がチェックされます。

その2番目の関数定義には、ガード節がありますwhen n > 0です。つまり、この関数は、引数n0より大きい場合にのみ一致します。結局のところ、数学的階乗関数は負の整数に対して定義されていません。

関数定義(パターンマッチングとガード句を含む)が一致しない場合、 FunctionClauseErrorが発生します。これは、負の数が定義されていないため、負の数を引数として渡すときにこの関数で発生します。

このFunctionClauseError自体は間違いではないことに注意してください。他のいくつかの言語でよく見られるように、 -10などの「エラー値」を返すと、未定義の関数を呼び出してエラーの原因を隠してしまい、将来の開発者にとって巨大なバグが発生する可能性があります。

デフォルトパラメータ

構文を使用して、任意の名前付き関数にデフォルトのパラメータを渡すことができます: param \\ value

defmodule Example do
    def func(p1, p2 \\ 2) do
        IO.inspect [p1, p2]
    end
end

Example.func("a")    # => ["a", 2]
Example.func("b", 4) # => ["b", 4]

キャプチャ機能

他のモジュールから関数をキャプチャするには、 &を使用します。キャプチャされた関数は、関数パラメータとして、または匿名関数内で直接使用できます。

Enum.map(list, fn(x) -> String.capitalize(x) end)

&を使用してより簡潔にすることができます:

Enum.map(list, &String.capitalize(&1))

引数を渡さずに関数をキャプチャするには、その文字列を明示的に指定する必要があります(例: &String.capitalize/1

defmodule Bob do
  def say(message, f \\ &String.capitalize/1) do
    f.(message)
  end
end


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow