「プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則」
この本の中で下記の文がよくわからんってなったのでGolangでコードを書いてみて理解したので解説。
「宣言型の表現」とは、コードの意図を伝えようとする時、できるだけ「命令型」よりも「宣言型」で表現することです。
例えば、与えられた整数の配列から、特定の条件を満たす要素のみを抽出する場合を考えます。
命令型のアプローチでは、ループを使用して条件に合致する要素を取得する必要がありますが、宣言型のアプローチでは、フィルタリングのためにGo言語の標準ライブラリに含まれる関数を使用することができます。
// 命令型の例
func getEvenNumbers(numbers []int) []int {
var evenNumbers []int
for _, number := range numbers {
if number % 2 == 0 {
evenNumbers = append(evenNumbers, number)
}
}
return evenNumbers
}
// 宣言型の例
func getEvenNumbers(numbers []int) []int {
return filter(numbers, func(number int) bool {
return number % 2 == 0
})
}
func filter(numbers []int, filterFunc func(int) bool) []int {
var filteredNumbers []int
for _, number := range numbers {
if filterFunc(number) {
filteredNumbers = append(filteredNumbers, number)
}
}
return filteredNumbers
}
この例では、filter
関数は、与えられた条件に基づいて配列をフィルタリングするための抽象化された関数です。
getEvenNumbers
関数は、filter
関数を使用して、与えられた配列の偶数要素のみをフィルタリングします。
このアプローチは、命令型のアプローチよりも宣言型であり、関数の名前や引数、戻り値を見るだけで、コードの意図が明確に伝わるという利点があります。
もっと簡単なコード
// 命令型の例
func sum(numbers []int) int {
total := 0
for _, number := range numbers {
total += number
}
return total
}
// 宣言型の例
func sum(numbers []int) int {
return reduce(numbers, func(acc, number int) int {
return acc + number
}, 0)
}
func reduce(numbers []int, reduceFunc func(int, int) int, initialValue int) int {
result := initialValue
for _, number := range numbers {
result = reduceFunc(result, number)
}
return result
}
宣言型の例では、reduce
関数を使用して、数値の配列を単一の値にまとめる関数を作成しています。reduce
関数は、与えられた関数によって値を累積することができ、最終的な値を返します。
sum
関数は、reduce
関数を使用して、与えられた配列の値の合計を計算します。
命令型のアプローチでは、ループを使用して値を合計していますが、宣言型のアプローチでは、配列を累積する抽象化された関数を使用しています。このようなアプローチは、コードの意図をより明確に伝え、再利用性が高いという利点があります。