高階関数と匿名関数

Go では高階関数もサポートされている。
引数の型のところに関数の型を書けばいい。関数の型は func(引数の型のリスト) 返り値の型 というふうに書く。説明するより、例を見たほうが早いだろう。

package main

import "fmt"

func square(x int) int {
    return x * x
}

func cube(x int) int {
    return x * x * x
}

func sumOf(f func(int) int, m, n int) int {
    a := 0
    for ; m <= n; m++ {
        a += f(m)
    }
    return a
}

func main() {
    fmt.Println("SUm of squares:", sumOf(square, 1, 5))
    fmt.Println("SUm of cubes: ", sumOf(cube, 1, 5))
}

sumOf が高階関数。最初の引数が関数になっていて、f func(int) int と書いてあるのがそれだ。
実行すると:

^o^ > go run sumof.go
SUm of squares: 55
SUm of cubes:   225

あたりまえだけど、きちんと動く。

さて、上の例にある squarecube みたいな短い関数ならわざわざ定義してから使わなくても、使う場所、つまり sumOf の引数のところに書いてしまうこともできる。匿名関数、または無名関数ってやつだね。こんどはこの匿名関数を使ってみよう。

package main

import "fmt"

func sumOf(f func(int) int, m, n int) int {
    a := 0
    for ; m <= n; m++ {
        a += f(m)
    }
    return a
}

func main() {
    fmt.Println("Sum of squares:", sumOf(func(x int) int { return x * x }, 1, 5))
    fmt.Println("SUm of cubes: ", sumOf(func(x int) int { return x * x * x }, 1, 5))
}
^o^ > go run sumof2.go
Sum of squares: 55
SUm of cubes:   225

この通り、匿名関数をつかっても期待通りに動く。とはいえ、匿名関数も型を明示的に書かなきゃいけないのはちょっとお手軽感がないなぁ。