この記事ではプログラミングの関数を解説します。
関数とは?
関数(function)とは「あるデータを受け取って、何かの処理をして、データを返す」仕組みです。
たとえば、以下は2つの整数を受け取って合計する関数の例です。
let answer = sum(1, 2);
console.log(answer); // 3
1行目の sum(1, 2)
が関数です。
sum(1, 2)
は「1」と「2」を受け取って、それらを合計して、「3」を返しています。
- あるデータを受け取って→「1」と「2」を受け取って
- 何らかの処理をして→それらを合計して
- データを返すもの→「3」を返す関数
このように「あるデータを受け取って、何らかの処理をして、データを返す仕組み」を関数といいます。
ユーザー定義関数と組み込み関数
関数には2種類あります。
ユーザー定義関数と組み込み関数です。
ユーザー定義関数とは、あなたが自由に作る関数です。あなた以外でも、プログラマが自分で作った関数を「ユーザー定義関数」といいます。
組み込み関数とは、プログラミング言語に備わっている関数です。プログラマが定義しなくても、あらかじめ使えるようになっています。定義済み関数ともいいます。
たとえば、JavaScriptで使う「console.log」は組み込み関数のひとつです。画面に文字列などを表示できる関数ですね。これは自分で作らなくても、最初から使うことができます。
console.log("Hello, World")! // JavaScriptで定義されている関数
開発の現場で「ユーザー定義関数」や「組み込み関数」という言葉を使う機会は多くありませんが、プログラミング言語の解説や公式ドキュメントなどには「組み込み関数」という言葉がよく登場します。
たとえば「print関数はPythonの組み込み関数なので、定義することなく呼び出せます」といった具合です。
関数には「自分で定義するものと」「プログラミング言語に組み込まれているもの」の2つがあるんだな〜という程度に覚えておいてください。
関数の構成要素
関数は以下の4つの要素からできています。
- 関数宣言
- 関数名
- 引数(型)
- 戻り値(型)
関数宣言
関数宣言とは、文字通り、関数を宣言する部分です。
関数を書くよ!というキーワードを書くことで関数宣言ができます。
これによって、コンピュータがそこに関数が書かれていることを理解できます。
関数宣言のためのキーワードはプログラミング言語ごとに異なります。
JavaScriptの場合はfunctionキーワードを使います。
function () { // 関数宣言
}
関数名
関数宣言のあとに関数名を書きます。関数名は「その関数が何をするのか?」がわかるようなものにします。
たとえば、ウェブサイトから画像をダウンロードする関数なら「downloadImage」のようにするとわかりやすいです。
function downloadImage() { // 関数名には「その関数の役割」を反映するとわかりやすい
}
引数
引数(ひきすう)とは、その関数に入力するデータのことです。
外部から関数に「引き渡す数」だから引数です。
引数は関数名のあとに丸括弧を書いて、その中に書きます。
function downloadImage(fileName) { // fileNameが引数
console.log(fileName); // 引数(fileName)は関数の中で変数として使える
}
ここに書いた引数は、関数の中で変数として使うことができます。
関数を使うときに、引数に渡した変数が関数の中に引き渡されるイメージです。
引数は複数書くこともできます。複数書く場合は、引数名は異なるものにしなくてはいけません。
function downloadImage(fileName, maxFileSize) { // fileNameとmaxFileSizeが引数
console.log(fileName);
console.log(maxFileSize);
}
プログラミング言語の種類によっては、引数の前後に型を書くこともあります。
たとえば、C#では以下のように引数の前にデータ型を書きます。
public static void DownloadImage(string fileName, int maxFileSize) // stringとintが引数の型
{
System.Console.WriteLine(fileName);
System.Console.WriteLine(maxFileSize);
}
戻り値
戻り値は、関数の中の処理が終わったあとに外部に戻す値です。
返り値と呼ぶこともあります(読み方が「かえりち」になり、誤解を招きそうなので、口頭では戻り値ということが多いです。)
戻り値はreturnというキーワードを書いてから、その後ろに書きます。
function downloadImage(fileName, maxFileSize) {
// ここに画像をダウンロードする処理を書く
return downloadedImage; // ダウンロードした画像をreturnして関数の呼び出し元に返す
}
関数を使うときは、関数名の前に変数をおいて「変数 = 関数()」とすると、関数の戻り値を外部の変数に代入することができます。
function downloadImage(fileName, maxFileSize) {
// ここに画像をダウンロードする処理を書く
return downloadedImage;
}
//「猫の画像.jpeg」と「100」を引数にして関数を呼び出す
// 戻り値の「downloadedImage」を変数「image」に代入して使える
const image = downloadImage("猫の画像.jpeg", 100);
プログラミング言語の種類によっては、戻り値の型を書く必要があります。
戻り値の型は、たいてい関数名の前に書きます。
詳しくは【言語別】関数の書き方を参照してください。
関数の使い方
関数の使い方は簡単です。次のようにして使います。
関数名();
関数が引数を受け取る場合は次のようにします。
関数名(引数1, 引数2, 引数3, ...);
関数の後に丸括弧を書いて関数を実行することを「関数を呼び出す(コールする)」といいます。
関数を呼び出している部分を「呼び出し側」ということもあります。
上記のように関数は関数名(引数1, 引数2, ...)
のように書くだけで、呼び出すことができます。
関数から戻り値を取得する場合は、次のようにします。
let 変数 = 関数名(引数1, 引数2, 引数3, ...);
このようにして、関数からの戻り値を変数に代入できます。
関数が戻り値を返さない場合は、変数に値は代入されません。
また、関数が戻り値を返す場合に、その戻り値を受け取らなくても問題ありません。
関数の作り方
ここでは関数を作ってみましょう。
ITエンジニアとして働くと毎日のように関数を作ることになります。
しっかり覚えましょう。
今回はJavaScriptを使って、引数に与えられた数値を2乗して返す関数(square)を作ります。
完成形は以下の通りです。
function square(value) {
return value ** 2;
}
以下のように数値を渡すと2乗した値を返します。
const value = 2;
const valueOfSquared = square(2);
console.log(valueOfSquared); // 4
1. 関数の構造を関数
まずは関数全体の構造を書きます。
functionキーワードを使って関数宣言をしつつ、関数名をsquareとして全体の構造を書きます。
function square() {
}
2. 引数を書く
次に、関数の引数を書きます。
square関数は、数値を受け取って2乗して返す関数なので数値型の変数をひとつ受け取ればOKです。
引数名をvalueとします。
function square(value) {
}
3. 戻り値を書く
続いて、受け取った値を2乗する処理と戻り値を書きます。
2乗の計算にはべき乗演算子を使います。
引数で受け取ったvalueを2乗して、return文で戻り値として返します。
function square(value) {
return value ** 2; // 2乗した値を戻り値に設定する
}
4. 完成
以上で関数は完成です。簡単ですね。
作った関数を使ってみましょう。
function square(value) {
return value ** 2; // 2乗した値を戻り値に設定する
}
console.log(square(2)); // 4
console.log(square(3)); // 9
console.log(square(4)); // 16
受け取った値を正しく2乗できていることがわかりますね。
なぜ関数を使うのか?
プログラミングで関数を使う理由は3つあります。
- 何度も使う処理をひとつにまとめるため
- コードを整理して使いやすくするため
- 「処理」を1つのデータとして扱えるようにするため
1. 何度も使う処理をひとつにまとめるため
プログラミングをしていると何度も同じ処理を書かなければいけないことがあります。
たとえば、以下のような場合です。
const arrayA = [7, 1, 4, 2, 8];
// arrayAの中から最大値を探す
let maxOfA = arrayA[0];
for (let element of arrayA) {
if (element > maxOfA) {
maxOfA = element;
}
}
console.log(maxOfA);
const arrayB = [9, 5, 6, 7, 3];
// arrayBの中から最大値を探す
let maxOfB = arrayB[0];
for (let element of arrayB) {
if (element > maxOfB) {
maxOfB = element;
}
}
console.log(maxOfB);
ここではarrayA
とarrayB
からそれぞれ最大値を探しています。
対象とする配列が違うだけで、最大値を探す処理は全く同じです。
このようなときに同じ処理を2回書くのは面倒です。
同じものを2回書いてから間違いに気付いたとき、2箇所とも直さなければいけません。
これが3回、4回と増えていくと手に負えなくなります。
こんなときに関数を使います。
ここでは「①ある配列を受け取って、②その配列から最大値を探し、③最大値を返す」ような関数を作れば、同じ処理を1回書くだけで済みます。
これを関数に書いてみましょう。
// 関数を作る
function findMax(array) { // ①ある配列を受け取って
// ②その配列から最大値を探し
let maxValue = array[0];
for (let element of array) {
if (element > maxValue) {
maxValue = element;
}
}
// ③最大値を返す
return maxValue;
}
const arrayA = [7, 1, 4, 2, 8];
const maxOfA = findMax(arrayA); // 同じ処理を1つにまとめた
console.log(maxOfA);
const arrayB = [9, 5, 6, 7, 3];
const maxOfB = findMax(arrayB); // 同じ処理を1つにまとめた
console.log(maxOfB);
ここではfindMaxという関数を作っています。
関数を作ったことで、同じ処理を2回書く必要がなくなりました。
これが関数を作る第一のメリットです。
2. コードを整理して使いやすくするため
さきほどの例では2回書く処理をひとつの関数にまとめたことで、書く手間が減って楽になりました。
関数にまとめる前と後を比べると、関数にまとめたあとの方がスッキリと整理されていることに気付いたでしょうか。
このように処理を関数にまとめることでコードが整理されます。
コードが整理されると、管理しやすくなり開発がはかどります。
また、他の開発者にとっても読みやすくなるのでチーム開発も円滑になります。
これが関数を使うことの2つ目のメリットです。
3. 「処理」を1つのデータとして扱えるようにするため
ここからは応用編ですが、関数を使うことにはもう1つのメリットがあります。
処理を1つのデータのように扱えるようになることです。
少し難しい話なので、理解するのが辛くなったら読み飛ばしてください。
JavaScriptやPythonなどの言語では、関数を関数の引数や戻り値にすることができます。
これによってコードの再利用性を高めることができます。
たとえば、以下のような配列があるとします。
const array = [1, 2, 3, 4, 5];
ここでarray
のすべての要素を2倍にするコードを書きます。
const doubled = [];
for (let element of array) {
doubled.push(element * 2); // 要素を2倍して新しい配列doubledに追加する
}
console.log(doubled); // [2, 4, 6, 8, 10]
このとき、同じように配列のすべての要素の平方根を計算するコードも書きたくなりました。
どうすればいいでしょうか。
これを実現するには「要素を2倍する処理」と「要素の平方根を計算する処理」を関数の外から受け取れるようにすればいいです。
ここで関数を引数として受け取る関数を作ります。
ある配列を受け取って、任意の処理を適用する関数なので、apply関数としましょう。
function apply(array, func) { // 配列と関数を受け取る(ここでfuncに2倍や平方根の関数を渡す)
const result = [];
for (let element of array) {
result.push(func(element)); // 要素にfunc関数を適用する
}
console.log(result);
}
これで、apply関数を使えば、配列の全要素に対して「外部から与えられた任意の処理(func)」を適用できるようになりました。
apply関数を使って、配列の全要素を2倍するコードを書き換えてみましょう。
function double(element) {
return element * 2; // 値を2倍する関数
}
apply(array, double); // funcに値を2倍する関数(double)を渡す
// [2, 4, 6, 8, 10]
同じ結果が得られましたね。
次は、配列の全要素の平方根を計算するコードを書いてみましょう。
function squareRoot(element) {
return Math.sqrt(element); // 値の平方根を計算する関数
}
apply(array, squareRoot); // funcに平方根を計算する関数(squareRoot)を渡す
// [ 1, 1.4142135623730951, 1.7320508075688772, 2, 2.23606797749979 ]
簡単ですね。
「配列の全要素に同じ処理を適用する」という機能がapply関数にまとめているため、変わった処理(2倍か平方根か)だけを書き直せば、いいというわけです。
このようにある「処理」をデータのように、関数の外から渡せるようにすることで、コードの再利用性を高めることができるのです。
これが関数を使う3つ目のメリットです。
特殊な関数
関数には特殊な形式のものがあります。
ここでは特殊な関数を紹介します。
無名関数(関数式)
無名関数とは、その名の通り、名前のない関数です。
JavaScriptでは以下のように無名関数を定義します(JavaScriptでは関数式といいます)。
function () {
return "これは無名関数です";
}
関数名を書かずに定義していますね。
しかし、無名関数はこのままでは使えません。
関数を呼び出すために必要な名前がないからです。
変数に代入(バインド)して使用するか、後に紹介する高階関数に引数として渡すと使用できます。
const example = function () {
return "これは無名関数です";
}
console.log(example()); // これは無名関数です
高階関数の引数として渡すときに使うことが多いです。
関数名をつける必要がないので、コードをシンプルに記述できます。
以下の例ではボタン(button)がクリックされたときに、関数を呼び出すように設定しています。
button.addEventListener("click", function (event) {
console.log("無名関数が呼び出されました");
});
ボタンがクリックされたときの動作は「addEventListenerメソッド」で設定できます。
このメソッドの2番目の引数に関数を書くと、ボタンがクリックされたときにその関数を実行します(このようにあるイベントが発生したときに実行する関数をコールバック関数といいます)。
コールバック関数は「イベントが発生したときに実行する」ことが明らかです。
そのため関数名を書く意味がないことが多いのです。
こういうときにコールバック関数として、無名関数を割り当てます。
ラムダ式
プログラミング言語によっては「ラムダ式」という名称で、無名関数と同様の関数を定義できることがあります。
たとえばPythonではlambdaを使って無名関数を作成できます。
以下は引数に与えられた値を2乗する例です。map関数とlambdaを組み合わせて、リストのそれぞれの値を2乗します。
nums = [1, 2, 3, 4, 5]
squared_nums = list(map(lambda x: x ** 2, nums))
print(squared_nums) # [1, 4, 9, 16, 25]
このようにコードをシンプルに記述するために無名関数やラムダ式を使うことがあります。
アロー関数
アロー関数は無名関数の一種ですが、無名関数よりも短く書ける関数です。
無名関数と同様に、関数に命名の必要がない場合や、関数をシンプルに記述したい場合に使われます。
JavaScriptのアロー関数は次のように書きます。
const square = num => num ** 2;
console.log(square(2)); // 4
関数宣言や、丸括弧・波括弧を省略できるため非常に簡潔に定義できます。
※JavaScriptにおける無名関数とアロー関数にはいくつか違いがあります。詳細は公式ドキュメントのアロー関数の説明を参照してください。
非同期関数
非同期関数は、文字通り非同期に実行される関数です。
「非同期に実行される」とは、メインの処理とは別に、バックグラウンドで実行されるというような意味です。
たとえば、YouTubeで動画を再生するとき、サーバーから動画をダウンロードする処理は非同期に実行されます。
PCやスマホでは、サーバーにある動画を完全にダウンロードしてから動かすのではなく、少しずつダウンロードしながら、同時に再生処理をします。
これによって動画のダウンロードを待たずに、動画をスムーズに見ることができます。
これが「非同期に実行する」ということです。
非同期関数は、このような非同期処理をするための関数です。
以下はJavaScriptで非同期関数を書いた例です。
async function fetchWebSite() {
const response = await fetch(`https://example.com`);
return response;
}
// async functionとして非同期関数を定義する
async function getWebSiteContent() {
try {
console.log("サイトからデータを取得しています...");
const content = await fetchWebSite(); // awaitでデータを待つ
console.log(`データを取得しました: ${content}`);
} catch (error) {
console.error(`エラーが発生しました ${error}`);
}
}
getWebSiteContent();
非同期関数はasync
キーワードを使って宣言します。async
と宣言した関数の中では、await
キーワードを使うことができます。
await
キーワードを使うことで非同期関数の中で一時停止して、外部の処理を待つことができます。
高階関数
高階関数は「引数に関数を渡すことができる」か「戻り値として関数を返すことができる」のどちらか(もしくは両方)の特徴を持つ関数です。
無名関数の例として紹介したJavaScriptの「addEventListener」は高階関数のひとつです。引数に関数を受け取ることができるからです。
他に、戻り値として関数を返す関数も高階関数のひとつです。
以下は、ステータスコードの値によって異なる処理を返す高階関数の例です。
function onSuccess() {
console.log("処理は成功しました!");
}
function onError() {
console.log("処理は失敗しました...");
}
function getFunction(statusCode) {
if (statusCode == 200) {
return onSuccess; // onSuccess関数を戻り値として返す
} else {
return onError; // onError関数を戻り値として返す
}
}
let func = getFunction(200);
func(); // 処理は成功しました!
func = getFunction(404);
func(); // 処理は失敗しました...
このように関数を引数や戻り値として利用することで、任意の処理を変数のように扱うことができます。
関数とメソッド
関数とよく混同されるものとして「メソッド」があります。
メソッドと関数の違いは「クラスに所属しているかどうか」です。
特定のクラスに属している関数をメソッドといいます。
一方、特定のクラスに属していない場合に関数と呼びます。
詳しくはメソッドとは?を参照してください。
【言語別】関数の書き方
言語別の関数の書き方を紹介します。
C言語
C言語では関数名の前に戻り値の型を記述します。戻り値や引数がない場合はvoidと記述します。
void helloWorld(void) {
printf("Hello World!\n");
}
戻り値や引数がある場合は次のように記述します。以下は、戻り値も引数もintの場合です。
int square(int value) {
return value * value;
}
関数の呼び出しは以下のとおりです。
int main(void){
helloWorld();
int squaredNum = square(5);
printf("square(5) = %d\n", squaredNum);
}
Python
Pythonではdefキーワードを使って関数を定義します。
def hello_world():
print('Hello, World!')
戻り値や引数がある場合でも型を書く必要はありません(型を書くことも可能です)。
def square(value):
return value ** 2
関数を呼び出すには以下のようにします。
hello_world() # Hello, World!
squared_num = square(5)
print(squared_num) # 25
JavaScript
JavaScriptではfunctionキーワードを使って関数を定義します。
function helloWorld() {
console.log("Hello, World!");
}
function square(value) {
return square ** 2;
}
関数を呼び出すには以下のようにします。
helloWorld(); // Hello, World!
squaredNum = square(5);
console.log(squaredNum); // 25
Ruby
Rubyではdefキーワードを使って関数を定義します。
def hello_world
puts "Hello, World!"
end
def square(value)
value * value
end
関数を呼び出すには以下のようにします。
hello_world() # Hello, World!
squared_num = square(5)
puts squared_num # 25
PHP
PHPではfunctionキーワードを使って関数を定義します。
function helloWorld() {
echo "Hello World!\n";
}
function square($value) {
return $value ** 2;
}
関数を呼び出すには以下のようにします。
helloWorld(); // Hello World!
$squaredNum = square(5);
echo $squaredNum; // 25
Java
Javaでは修飾子(modifier)と戻り値の型とともに関数を宣言します。
また、引数にも型を定義する必要があります。
public static void helloWorld() {
System.out.println("Hello, World!");
}
public static int square(int value) {
return value * value;
}
関数を呼び出すには以下のようにします。
helloWorld(); // Hello, World!
int squaredNum = square(5);
System.out.println(squaredNum); // 25
C#
C#では修飾子(modifier)と戻り値の型とともに関数を宣言します。
また、引数にも型を定義する必要があります。
public static void HelloWorld()
{
System.Console.WriteLine("Hello, World!");
}
public static int Square(int value)
{
return value * value;
}
関数を呼び出すには以下のようにします。
HelloWorld(); // Hello, World!
int squaredNum = Square(5);
System.Console.WriteLine(squaredNum); // 25
まとめ
この記事ではプログラミングの「関数」を解説しました。
- 関数(function)は「あるデータを受け取って、何かの処理をして、データを返す」仕組み
- 関数を使うメリットは以下の3つ
- 何度も使う処理をひとつにまとめるため
- コードを整理して使いやすくするため
- 「処理」を1つのデータとして扱えるようにするため
- 関数は「関数宣言」「関数名」「引数(型)」「戻り値(型)」などから構成される
関数はプログラミングには必須です。関数を使いこなせればコードをきれい整理することができます。コードが整理できると、プログラミングがやりやすくなり、生産性が高まります。
練習をたくさん積み重ねて、ぜひ関数を使いこなしてください。