無名関数の即時実行
無名関数について話を進める前に、まずは通常の関数(名前付き関数)を実行する手順をおさらいしておきましょう。
名前付きの関数では、関数を宣言する際に名前をつけておき、それを呼び出すことで関数内に書き込まれた処理が実行されます。
次に示すのは、JavaScript(上)とKotlin(下)で、名前付き関数を宣言して実行する例です。
See the Pen
Named Function by ROYDO (@roydo)
on CodePen.
Kotlin
ここまでは何の問題もないですね。では次に、無名関数を見ていきましょう。
JavaScriptの場合、無名関数では関数全体を( )(丸括弧)で囲み、名前をつけずに関数を記述します。
Kotlinの場合は、{}(波括弧)で全体を囲みます。(Kotlinの場合、ラムダ式と呼ばれます)
しかし、無名なので当然ですが、関数を後で呼び出すことができません。
なので、関数を定義してそのまま実行(即時実行)しなければ、関数を実行できないということになります。
下は、無名関数を即時実行している例です。
See the Pen
Anonymous Function by ROYDO (@roydo)
on CodePen.
Kotlin
このように無名関数を実行したければその場で実行するしかないので、普通に考えれば使い勝手が悪くて、無名関数が存在する意味がないように思えますよね。
ですが、プログラミングではわざわざ関数に名前をつけて宣言する方が面倒くさいという場面が多々あるんです。
それはどういう場合なのか?次の章で詳しくみていきましょう!
…と、その前に。
JavaScriptでは、アロー関数を使うことで、下のように関数をよりシンプルに記述することができます。
See the Pen
Anonymous function(Arrow) by ROYDO (@roydo)
on CodePen.
以降、JavaScriptのコードはアロー関数で記述していきます。
POINT!
- ・名前付き関数は、宣言した関数を呼び出すことで好きなタイミングで実行できる!
- ・無名関数は名前がないので後から呼び出せず、基本的に即時実行するしかない!
- ・一見、使い道がないように思える無名関数だが、実は色々なところで大活躍する!
無名関数が役立つ場面
普通なら、即時実行しないと使えない無名関数は使い勝手が悪いのですが、無名関数の方が都合が良い場合もあります。
その代表例が、『関数を引数として別の関数に渡すとき』です。
関数を引数として渡す場合、関数を渡す時点では実行する必要がない…と言えます。
であれば、関数を渡すのと同時に関数を定義できた方が、どのような関数が渡されているかが明確になり、コードが見やすくなります。
論より証拠ということで、配列の要素を一つ一つ取り出して処理を行い、新しい配列を作り出すmap()を使った例を見てみましょう。
無名関数の前に、まずは名前付き関数を宣言して渡してみます。
See the Pen
Named Function by ROYDO (@roydo)
on CodePen.
Kotlin
上の例では、まず doubleTheNumber という名前付きの関数を宣言し、渡された引数に2をかけて倍にした値を返す…という処理を定義しています。
そして、その関数をmap()に渡すことで、配列の要素の値(数値)がそれぞれ2倍になった新しい配列を作成しています。
このように、名前付き関数を引数として別の関数に渡す場合、その関数の処理の内容を知りたければ名前付き関数が記述されている箇所を探して、その中身を確認するしかありません。
この例で言えば、doubleTheNumberの処理の内容を知るためには、doubleTheNumber()の記述場所を探して中身を確認する必要がある…ということです。
例のように数行程度のプログラムであれば目的の関数を探すのも難しくありませんが、コードの行数が増えてくるとそれが大変になってきます。
doubleTheNumber関数を他のところで何度も使い回すわけではないのなら、わざわざ関数に名前をつけて宣言するメリットはありません。
このようなケースでは、無名関数をその場で定義して渡すのが一般的です。
具体的には次のようになります。
See the Pen
Argument function1 by ROYDO (@roydo)
on CodePen.
Kotlin
無駄な関数の宣言の記述がなくなって、ずいぶんスッキリしましたね!
map()にどのような処理を行う関数を渡しているのかも、map()の中身を見れば分かるようになり、処理の内容を把握するのも楽になりました。
無名関数は、単独では即時実行しなければ実行されないので意味がありませんが、関数の引数として利用する場合、呼び出し元の関数が呼ばれた時点で無名関数が実行されることになります。
なので、『即時実行しないと使えない』というデメリットが無くなり、それによって様々な使い道が出てくるというワケです。
ちなみにKotlinの場合、引数が一つだけの場合はitで表すことができるので、よりシンプルな記述になっています。
また、無名関数を渡すことで関数の名前を考えたりする時間を節約できるのも、地味に大きなメリットです。
私たち日本人にとって、関数が行う処理の内容を適切な英単語に脳内変換するのは面倒な作業ですし、スペルミスをしてしまう確率も高いですよね。(そもそもスペルが出てこないとか)
その過程を省略できることには、大きな意味があると言えるでしょう。
ただし、ここで一つ注意点です。
関数を引数として別の関数に渡す場合、常に無名関数を利用すれば良いわけではありません。
特に、処理が複雑なものであったり、他のところでも使い回したりするような場合は、名前付き関数を宣言して渡した方がメリットが大きくなります。
プログラミングの参考書等では、無名関数を利用できるところは無名関数を利用して、シンプルな記述で説明していることが多いですが、常にその書き方が絶対というわけではないことを覚えておくと良いと思います。
また、プログラミングを学ぶ際の大事なポイントなのですが、1から100まで一度に理解できなくてもOKです。
最初は、『よく分からないけど、こういうふうに書けばエラーにならずにコードがちゃんと実行されるんだなぁ』…ぐらいでも構いません。
参考書を読み返したり、自分でコードを繰り返し書いていくうちに、『あれはこういう意味だったのか!』というふうに、後になって点と点が繋がる感覚を味わえると思います。
POINT!
- ・関数の引数として関数を渡す必要がある場合、無名関数が活躍する!
- ・無名関数を渡すことで、処理の内容を確認しやすくなる!
- ・無名関数を利用することで、関数の名前を考えたりする手間を省ける!