Section 1.19 関数の参照

今回は、変数を使って関数を呼び出してみるね。
えっ、そんなことできるの?
うん。
まぁ、そんなにしょっちゅう使うわけじゃないんだけど、わりと便利だし、やり方もそんなに難しくないから。
ふぅん…そうなんだ。
それってどうやるの?
ん〜、まぁ実際にスクリプトを見てみるのが早いかな。
ってことで、これが変数を使って関数を呼び出すやり方。

<参照を使った関数呼び出しの例>

// plus 関数を定義します
function plus(x, y)
{
    return x + y;  // 引数 x と y の和を返します
}

System.inform("1 + 2 = " + plus(1, 2));  // 普通に関数を呼び出します

var func = plus;  // plus 関数への参照として func を初期化します

System.inform("1 + 2 = " + func(1, 2));  // 変数 func を使って plus 関数を呼び出します

ちょっと実行してみて。
うん。
……「1 + 2 = 3」って2回表示されたね。
ってことは、func(1, 2) の方もちゃんと plus 関数を呼び出せてるってことだよね。
そ。で、変数 func を初期化してるとこに注目してみて。
あ、plus にカッコと引数がついてないね。
そう、そこがポイント。
func = plus(1, 2);』って書くと func には戻り値の 3 が代入されるんだけど、 カッコと引数をつけずに『func = plus;』って書くと、変数 funcplus 関数と同じように使えるようになるんだ。
で、これを関数の参照っていうの。
へぇ…でも、これって何かメリットあるの?
例えば、こういうときに参照を使うと便利かな。

<関数の参照の使用例>

// 上から足し算、引き算、掛け算、割り算をした結果の文字列を返す関数を定義しています
function add(x, y)      {return x + " + " + y + " = " + (x + y);}
function subtract(x, y) {return x + " - " + y + " = " + (x - y);}
function multiply(x, y) {return x + " * " + y + " = " + (x * y);}
function divide(x, y)   {return x + " / " + y + " = " + (x / y);}

// 計算をする関数を定義しています(引数は上で定義しているどれかの関数への参照になります)
function calculate(func)
{
    // 1つ目の数値を受け取ります
    var x = System.inputString("""1つ目の数字を入力してください。""");
    if(x === void)
        return;  // キャンセルされた場合は計算せずに return します

    // 2つ目の数値を受け取ります
    var y = System.inputString("""2つ目の数字を入力してください。""");
    if(y === void)
        return;  // キャンセルされた場合は計算せずに return します

    // 引数で指定されている関数を呼び出して、計算結果を表示します
    System.inform(func(+x, +y), "計算結果");
}

calculate(add);  // 足し算をします

なんか複雑なスクリプトだね…
見た目はね。でもほとんど今までやったことの組み合わせだから解るはずだよ。
そなの?
うん。
じゃ、まずは実行してみよっか。
おっけー。

最初に表示された入力を受け取るウィンドウ

これって、何か数字を入力すればいいの?
うん。適当な数値を入力して OK ボタンを押して。
わかった。
じゃあ、「123」って入力して、OK、と。

2回目に表示された入力を受け取るウィンドウ

また入力ウィンドウが表示されたけど、これも適当な数字を入力すればいいの?
うん、そう。
じゃあ、今度は「456」で、OK。

計算結果が表示されたメッセージボックス

あっ、これってさっき入力した数字を足し算した結果だよね。
ん。これは入力した2つの数字を足した結果を表示するスクリプトなんだ。
それじゃ、スクリプトの方を見ていくね。
は〜い!
まず関数を定義してる部分から。

// 上から足し算、引き算、掛け算、割り算をした結果の文字列を返す関数を定義しています
function add(x, y)      {return x + " + " + y + " = " + (x + y);}
function subtract(x, y) {return x + " - " + y + " = " + (x - y);}
function multiply(x, y) {return x + " * " + y + " = " + (x * y);}
function divide(x, y)   {return x + " / " + y + " = " + (x / y);}

この4つの関数は、xy っていう2つの引数を受け取って、 それぞれ足し算、引き算、掛け算、割り算をした結果を文字列にして返してるわけだけど、これはわかるよね。
うん、でもなんか書き方がいつもと違うよね。
スペースを節約するために全部1行で書いちゃってるから、確かにちょっと違和感があるかもしれないけど、 こんな書き方もできるってのは §1.1 で説明したよね。
あ、そうだったね。
じゃあ次は calculate 関数ね。

// 計算をする関数を定義しています(引数は上で定義しているどれかの関数への参照になります)
function calculate(func)
{
    // 1つ目の数値を受け取ります
    var x = System.inputString("""1つ目の数字を入力してください。""");
    if(x === void)
        return;  // キャンセルされた場合は計算せずに return します

    // 2つ目の数値を受け取ります
    var y = System.inputString("""2つ目の数字を入力してください。""");
    if(y === void)
        return;  // キャンセルされた場合は計算せずに return します

    // 引数で指定されている関数を呼び出して、計算結果を表示します
    System.inform(func(+x, +y), "計算結果");
}

最初に inputString メソッドで入力を受け取ってるね。
うん。最初に定義した4つの関数の引数に指定する2つの数値をここで取得してるの。
ちなみにキャンセルボタンが押されたら、計算せずにすぐ return するよ。
その次の inform メソッドのところで関数の参照を使ってるんだよね?
そう。calculate 関数の引数 func が関数の参照になってて、 inform メソッドの第1引数のところで func を使って関数を呼び出してるの。
だから、例えば…

calculate(add);  // 足し算をします

こうやって、引数に add を指定して calculate 関数を呼び出すと、 引数の funcadd 関数への参照になるから、calculate 関数の中では…

System.inform(add(+x, +y), "計算結果");

こう書くのと同じことになるワケ。
なるほどね〜。
あ、でも、それだったら最初からこう書いとけばいいんじゃないの?
足し算しかしないんならそれでいいんだけど、関数の参照を使うと他の計算が簡単にできるようになるんだ。
他の計算って、引き算と掛け算と割り算のこと?
そ。最初に定義した subtract, multiply, divide 関数の参照を引数に指定すると、 それぞれ引き算、掛け算、割り算ができるんだ。

calculate(subtract);  // 引き算をします
calculate(multiply);  // 掛け算をします
calculate(divide);    // 割り算をします

試しに、さっきのスクリプトcalculate(add); の行を calculate(subtract); に書き換えて実行してみて。 今度は引き算ができるはずだから。
うん、わかった。

<実行結果(最初に 123、次に 456 を入力)>

計算結果が表示されたメッセージボックス

ほんとだ。引き算の結果が表示されたね。
関数の参照を使うと、引数に指定する関数を変えるだけで色んな処理ができるんだ。
確かに便利だね〜。
…でも、これって作るの難しくない?
ん〜、まぁ慣れないうちはちょっと難しいかもね。
とりあえず、参照を使うと変数を関数みたいに使えるってことは覚えといて。
うん、わかった。
あと、ついでに式中関数も紹介しとくね。
式中関数?
名前の通り式の中で定義される関数のこと。
例えばこんなの。

<式中関数の使用例(その1)>

var plus = function(x, y) {return x + y;};

System.inform("1 + 2 = " + plus(1, 2));

えっと、これって関数を変数に代入してるの?
ん、そんな感じだね。
まぁ、実際には変数 plus には、この関数への参照が代入されるんだけど。
こうやっても plus は関数として使えるようになるんだ。
ふ〜ん…あ、この関数名前がないよ?
うん。式中関数には名前がないんだ。だから匿名関数とも呼ばれてるの。
式中関数は変数を使って呼び出せるから、関数自体に名前は必要ないでしょ。
あ、そっか。
でも、わざわざこんなふうにしなくても、普通に関数を定義すればいいんじゃない?
ま、普通はそうだね。
でも、一時的にしか使わないような関数に使ったりとか、あと引数としても使えると思うよ。
引数として使うって?
例えばこんな感じかな。

<式中関数の使用例(その2)>

// calculate(add); と同じ結果になります
calculate(function(x, y) {return x + " + " + y + " = " + (x + y);});

このスクリプトを実行すると、calculate(add); を実行した時と同じ結果になるんだ。
つまり、こうやっても足し算ができるの。
え、そうなの?
引数に指定してる式中関数が add 関数と同じになってるでしょ。
あ、ほんとだ。式中関数の中身が add 関数と同じだね。
こんなふうに、引数に関数の参照を指定する代わりに、式中関数を使うこともできるんだ。
なるほどねぇ。
でも、これも使い方が結構難しそうだよね…
まぁ、式中関数についても、とりあえずこんなことが出来る、ってくらいで OK だから。
うん、りょーかい。
さて、これで一通り関数について見てきたことだし、次回は関数のまとめってことで、§1.12のスクリプトを、関数を使って書き換えてみるよ。
え、わざわざ関数にするの?
ん、あのスクリプトは第2章でも使うからね。関数にしといた方が使いやすくなるんだ。
ちなみに、第1章は次回で最後だよ。
あ、ついに次で第1章終わるんだ。
でも、第1章って長かったよねぇ…
TJS は基本的なことだけでも色々あるからねー。ま、とりあえず次で一区切りかな。
それじゃ、また次回ね!


前へ | TOP | 次へ