操作方法

高階関数紹介

2008-12-21
MAS

目次

はじめに

高階関数とは

プログラミング言語において、関数を引数にしたり、あるいは関数を戻り値とするような関数の事である。 高階関数 - Wikipedia

引数化

高階関数へ行く前に

例で見て行きましょう

今回こういうのはなしで

function sum1to10() {
    return 55;
}

function sum1to10() {
    return 1+2+3+4+5+6+7+8+9+10;
}

function sum1to10() {
    return 11*10/2;
}

話の都合上これで

function sum1to10() {
    var sum = 0;
    for (var i = 1; i <= 10; i++) {
        sum += i;
    }
    return sum;
}

今度はこれ

簡単ですね

function sum11to15() {
    var sum = 0;
    for (var i = 11; i <= 15; i++) {
        sum += i;
    }
    return sum;
}

並べてみると、似てますね

function sum1to10() {
    var sum = 0;
    for (var i = 1; i <= 10; i++) {
        sum += i;
    }
    return sum;
}
function sum11to15() {
    var sum = 0;
    for (var i = 11; i <= 15; i++) {
        sum += i;
    }
    return sum;
}

引数化します

function sumAtoB(a, b) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += i;
    }
    return sum;
}
function sum1to10() {
    return sumAtoB(1, 10);
}
function sum11to15() {
    return sumAtoB(11, 15);
}

結果として

関数の引数化

ここからが本番

例です

こうなります

function sumOddAtoB(a, b) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += i * 2 - 1;
    }
    return sum;
}
function sumOdd1to6() {
    return sumOddAtoB(1, 6);
}

1番目から6番目の奇数を足すのでsumOddAtoB(1, 6)です。

奇数算出を関数化します

function sumOddAtoB(a, b) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += odd(i);
    }
    return sum;
}
function odd(n) {
    return n * 2 - 1;
}

これはどうでしょう

2乗する関数を書きます

function sumPow2AtoB(a, b) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += pow2(i);
    }
    return sum;
}
function pow2(n) {
    return n * n;
}

そっくり

function sumOddAtoB(a, b) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += odd(i);
    }
    return sum;
}
function sumPow2AtoB(a, b) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += pow2(i);
    }
    return sum;
}

毎度おなじみ、引数化

function sumFunctionAtoB(a, b, f) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += f(i);
    }
    return sum;
}

呼び出し方

function sumFunctionAtoB(a, b, f) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += f(i);
    }
    return sum;
}
function pow2(n) {
    return n * n;
}
var total = sumFunctionAtoB(1, 6, pow2);

引数にそのまま書けば良いです。

結果として

たとえば偶数の和

function sumFunctionAtoB(a, b, f) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += f(i);
    }
    return sum;
}
function even(n) {
    return n * 2;
}
var total = sumFunctionAtoB(1, 6, even);

匿名関数

でも

こう書きます

function sumFunctionAtoB(a, b, f) {
    var sum = 0;
    for (var i = a; i <= b; i++) {
        sum += f(i);
    }
    return sum;
}
var total = sumFunctionAtoB(1, 6, function(n) {
    return n * n;
});

比べてみましょう

function pow2(n) {
    return n * n;
}
var total = sumFunctionAtoB(1, 6, pow2);
var total = sumFunctionAtoB(1, 6, function(n) {
    return n * n;
});

匿名なだけに「pow2」という名前がなくなっています。

わざわざ関数定義をしておく必要がないのでプログラムがすっきりします。

地域によって「匿名関数」ではなく「無名関数」だったり「関数リテラル」だったり。

高階関数の利用シーン

便利そうだけど……

高階関数が強力なのは分かった。

でもそんなの一生使わないよ、と思ったあなた。

そうでもないですよ。

例その1:ソート

var items = [32, 243, 12, 3, 7, 13];
items.sort(function(a, b) {
    // 逆順にソート
    return (a < b) ? 1 : -1;
});
document.write(items.join(', '));

sort()メソッドの引数に比較関数を渡すことができます。

比較関数の書き方次第でソートの順番を変えたり、より構造が複雑なオブジェクトのソートができます。

例その2:jQueryでAjax

$.ajax({
    ※一部省略
    success: function(data) {
        self.getRensoSuccess(data);
    },
    error: function(xhr, status, e) {
        self.writeRensoResult('取得失敗');
    }
});

成功したときの処理と失敗したときの処理の内容を引数として渡しています。

まとめ

まとめ

おまけ

Σ(シグマ)

今回作成した sumFunctionAtoB() 関数はΣに対応しています。

 b
 Σ f(n) ⇔ sumFunctionAtoB(a, b, f)
n=a
10
 Σ n ⇔ sumFunctionAtoB(1,10,function(n){return n;})
n=1
 5
 Σ n2 ⇔ sumFunctionAtoB(1,5,function(n){return n*n;})
n=1

今回はやりませんが、さらに突き進むと数列の和と数列の積を同様に扱えるようになります。

参考資料

本資料は「S6」というプレゼンテーションツールを利用させていただいています。

以上です