名前を明確にするために、どちらも機能です。1つは名前付き関数で、もう1つは匿名関数です。しかし、あなたは正しい、それらは多少異なる動作をするので、なぜそれらがそのように動作するのかを説明します。
2番目のから始めましょうfn
。Rubyのにfn
似たクロージャーlambda
です。次のように作成できます。
x = 1
fun = fn y -> x + y end
fun.(2) #=> 3
関数も複数の句を持つことができます:
x = 1
fun = fn
y when y < 0 -> x - y
y -> x + y
end
fun.(2) #=> 3
fun.(-2) #=> 3
では、別のことを試してみましょう。別の数の引数を期待する別の句を定義してみましょう:
fn
x, y -> x + y
x -> x
end
** (SyntaxError) cannot mix clauses with different arities in function definition
大野!エラーが発生しました!異なる数の引数を期待する句を混在させることはできません。関数には常に固定されたアリティがあります。
次に、名前付き関数について説明しましょう。
def hello(x, y) do
x + y
end
予想通り、それらには名前があり、いくつかの引数を受け取ることもできます。ただし、これらはクロージャーではありません。
x = 1
def hello(y) do
x + y
end
を表示するたびにdef
空の変数スコープを取得するため、このコードはコンパイルに失敗します。それはそれらの間の重要な違いです。それぞれの名前付き関数が白紙の状態で始まり、異なるスコープの変数がすべて混ざり合わないという事実が特に気に入っています。明確な境界があります。
上記の名前付きhello関数を無名関数として取得できます。あなたは自分でそれを述べました:
other_function(&hello(&1))
そして、あなたは尋ねました、なぜ私はhello
他の言語のようにそれを単に渡すことができないのですか?それは、エリクサーの関数が名前とアリティによって識別されるためです。したがって、2つの引数が必要な関数は、同じ名前であっても、3つが必要な関数とは異なります。したがって、単にを渡しただけではhello
、hello
実際に何を意味するのかわかりません。2つ、3つ、または4つの引数を持つもの?これは、異なるアリティの句を持つ無名関数を作成できないのと同じ理由です。
Elixir v0.10.1以降、名前付き関数をキャプチャする構文があります。
&hello/1
これにより、arity 1でローカルの名前付き関数helloがキャプチャされます。言語とそのドキュメント全体を通して、このhello/1
構文で関数を識別することは非常に一般的です。
これは、エリクサーが匿名関数を呼び出すためにドットを使用する理由でもあります。hello
関数として渡すだけではなく、明示的にキャプチャする必要があるため、名前付き関数と匿名関数には自然な違いがあり、それぞれを呼び出すための明確な構文により、すべてが少し明示的になります(Lispersはこれに精通しています) Lisp 1対Lisp 2の議論による)。
全体として、これらが、2つの機能があり、動作が異なる理由です。