JavaScriptで関数型プログラミングを体験しよう
皆さんは関数型言語をご存知でしょうか?
下記はプログラミング言語の系統図ですが、赤線で囲まれているのが関数型言語として分類されているプログラミング言語です。
下記にリンクを貼っておきます。
JavaScriptはオブジェクト指向言語ですが、関数型言語の影響も受けており、関数の組み合わせでコードを記述するプログラミング手法である関数型プログラミングを行うこともできます。
本記事では簡単なコードを使って関数型プログラミングについて紹介します。
用語の整理
関数型プログラミングでよく登場する用語としては次のようなものがあります。
第一級関数
無名関数
高階関数
第一級関数
プログラミング言語が第一級関数を持つと言われる場合、関数を他の関数への引数として渡したり、他の関数から返却したり、変数の値として代入したりすることができます。
MDNでの第一級関数の解説
下記にリンクを貼っておきます。
無名関数
プログラミング言語における無名関数とは、名前付けされずに定義された関数のことです。
ウィキペディアでの無名関数の解説
下記にリンクを貼っておきます。
高階関数
高階関数とは、第一級関数をサポートしているプログラミング言語において、関数を引数に取ったり関数を返したりする関数のことです。
ウィキペディアでの高階関数の解説
下記にリンクを貼っておきます。
とりあえず、次の3点を踏まえて本記事を読み進めてください。
1.JavaScriptは第一級関数をサポートしている
2.JavaScriptでは無名関数を定義できる
3.高階関数には「map」や「filter」などがある
関数型プログラミングのコード例
下記は2つの値の和と差を計算して返す簡単なコードですが、これを関数型プログラミングのコードに変えてみようと思います。
function add(num1, num2) {
return num1 + num2;
}
function sub(num1, num2) {
return num1 - num2;
}
console.log(add(10, 5));
console.log(sub(10, 5));
実行結果
15
5
次のようなcalcという高階関数を用意して、これを利用する形に上記のコードを変えてみます。(実行結果は同じですので省略します)
function calc(func, num1, num2) {
return func(num1, num2);
}
関数型プログラミングのコード例1
add関数とsub関数の関数名をcalcに渡しています。
function add(num1, num2) {
return num1 + num2;
}
function sub(num1, num2) {
return num1 - num2;
}
function calc(func, num1, num2) {
return func(num1, num2);
}
console.log(calc(add, 10, 5));
console.log(calc(sub, 10, 5));
関数型プログラミングのコード例2
add関数とsub関数を無名関数で定義して、それぞれをaddとsubという変数に代入して、その変数をcalcに渡しています。
const add = function(num1, num2) {
return num1 + num2;
};
const sub = function(num1, num2) {
return num1 - num2;
};
function calc(func, num1, num2) {
return func(num1, num2);
}
console.log(calc(add, 10, 5));
console.log(calc(sub, 10, 5));
関数型プログラミングのコード例3
add関数とsub関数を無名関数で定義して、直接calcに渡しています。
function calc(func, num1, num2) {
return func(num1, num2);
}
console.log(calc(function(num1, num2) {
return num1 + num2;
}, 10, 5));
console.log(calc(function(num1, num2) {
return num1 - num2;
}, 10, 5));
関数型プログラミングのコード例4
add関数とsub関数をアロー関数(無名関数を簡略化した表現)で定義して、それぞれをaddとsubという変数に代入して、その変数をcalcに渡しています。
const add = (num1, num2) => num1 + num2;
const sub = (num1, num2) => num1 - num2;
function calc(func, num1, num2) {
return func(num1, num2);
}
console.log(calc(add, 10, 5));
console.log(calc(sub, 10, 5));
関数型プログラミングのコード例5
add関数とsub関数をアロー関数で定義して、直接calcに渡しています。
function calc(func, num1, num2) {
return func(num1, num2);
}
console.log(calc((num1, num2) => num1 + num2, 10, 5));
console.log(calc((num1, num2) => num1 - num2, 10, 5));
以上のように、いろいろな形でコードを書くことができます。
mapを使ってみよう
mapは高階関数の一つですが、mapを使うことで配列の各要素を変換することができます。どのような変換を行うかは渡される関数に依存します。
下記は[1, 2, 3, 4, 5, 6]という配列に対して、配列の各要素を2乗に変換した新しい配列を作成するコードです。
const numbers = [1, 2, 3, 4, 5, 6];
const newNumbers = [];
for (let i = 0; i < numbers.length; i++) {
newNumbers.push(numbers[i] * numbers[i]);
}
console.log(newNumbers);
実行結果
[ 1, 4, 9, 16, 25, 36 ]
上記のコードに対してmapを使用する形に変更したのが下記のコードです。
const numbers = [1, 2, 3, 4, 5, 6];
const newNumbers = numbers.map(n => n * n);
console.log(newNumbers);
mapメソッドに配列の要素を2乗に変換するアロー関数が渡されています。
filterを使ってみよう
filterも高階関数の一つですが、filterを使うことで配列の各要素に対してある条件に合致する要素を取り出すことができます。どのような条件かは渡される関数に依存します。
下記は[1, 2, 3, 4, 5, 6]という配列から3より大きい要素を取り出して新しい配列を作成するコードです。
const numbers = [1, 2, 3, 4, 5, 6];
const newNumbers = [];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] > 3) {
newNumbers.push(numbers[i]);
}
}
console.log(newNumbers);
実行結果
[ 4, 5, 6 ]
上記のコードに対してfilterを使用する形に変更したのが下記のコードです。
const numbers = [1, 2, 3, 4, 5, 6];
const newNumbers = numbers.filter(n => n > 3);
console.log(newNumbers);
filterメソッドに要素の値が3より大きいかを判定するアロー関数が渡されています。
関数型プログラミングに興味を持たれた方へ
本記事では関数型プログラミングについてざっと紹介しましたが、「もっと関数型プログラミングについて知りたい」という方は下記の記事が関数型プログラミングについて詳しく説明されていますのでおすすめです。
下記にリンクを貼っておきます。