変数は箱じゃない

プログラム入門書だと、『変数とは何でも入れられる箱のようなもの』的な説明がされている場合が多い。
別に間違ってはいないんだけど、何かデザイナー受けは悪い気がする。
というか実際悪かった。


ので、別視点から解説してみる。

説明範囲
変数:関数
目標
プログラムのソースを見て、実行の流れを理解できる。
必要知識
中学レベルの数学。私は半分以上忘れている。
使用言語
Javascript っぽいものを想定している。

変数とは未知数 x だったんだよ!!

さっそくだが次の問題を考えてほしい。

(1) 2 * x = 10 のとき、 x の数は?
(2) x = 20 、 y = 2 * x のとき、 y の数は?

* は「掛ける (×)」の記号。小文字の X と見分けが付けづらいので * を使っているだけ。
(1) では x の数字を、 (2) では y の数字を計算すれば OK 。
計算できなかったら、残念ながら私では説明できそうもない。申し訳ありませんがお帰り下さい。


解けた人は、次のことを確認してほしい。

(1) "2 * x = 10" にしても "2 * y = 10" にしても "2 * z = 10" にしても、やることは一緒だよね。
(2) いっそ英字じゃなくなって、 "2 * 未知数 = 10" でも "2 * 何か = 10" でも、やっぱり一緒だよね。
(3) でも、 "2 * x * y = 10" と "2 * 何か * 何か = 10" は意味違うよね。
(4) 『何が入るか分からない部分』が一つ一つ把握できればそれでいいよね。
(5) いいんだ!

この際細かい部分は無視して、「これでいいんだ!」な気持ちで進みましょう。


長い上、テンションが一定してないので、後からまたまとめなおそう。

さて、ここから、あなたは本屋さんです。
個人経営、大手チェーン、どっちでもいいです。
兎に角あなたは本を売ってます。
ラインナップはこんな感じです。

本の名前   税別価格
カロリーメイトのススメ   ¥1,000
マン・イン・メガネ   ¥2,000
働きアリのデスマーチ   ¥3,000

絶望的な品揃えですが、「これでいいんだ!」な気持ちで進みましょう。*1


それでは本屋の嗜みです。
本の税別価格から、税込価格を計算してみましょう。

税込価格 = 税別価格 * 1.05

ですよね?
税別価格が具体的に決まってないので、税込価格が出せません。
なので、税別価格を決めてあげましょう。『カロリーメイトのススメ』は ¥1,000 です。

税別価格 = 1000

決めました。繋げるとこうなります。

税別価格 = 1000
税込価格 = 税別価格 * 1.05

言い換えましょう。

税別価格 = 1000 、税込価格 = 税別価格 * 1.05 のとき、 税込価格の数は?

計算できますよね。税込価格 は 1050 になりました。

プログラムっぽく書き始める (変数)

や、書くのは私ですが。
ここから、本屋とプログラムの間をいったりきたりし始めます。
何が書かれているのか、じっくりと追っていってください。

税別価格 = 1000
税込価格 = 税別価格 * 1.05
zeibetsu = 1000;
zeikomi  = zeibetsu * 1.05;

『税別価格』『税込価格』が英字なのは、プログラムでは日本語が使えない (場合が多い) からです。
行末の ; は、単純にそういう規則だから、みたいなものです。日本語の 。 に相当します。


重要なことは、プログラムは "上から順に" 計算されるということです。
以下のようなプログラムを例にとってみましょう。

zeibetsu = 1000;
zeikomi  = zeibetsu * 1.05;
zeibetsu = 2000;
zeikomi  = zeibetsu * 1.05;
zeibetsu = 3000;
zeikomi  = zeibetsu * 1.05;

このとき、 1 行目の zeibetsu は 1000 、 2 行目の zeikomi は 1050 です。

zeibetsu = 1000 、 zeikomi = zeibetsu * 1.05 のとき、 zeikomi = 1050

さて、では 3 行目以降はどうでしょう?
プログラムでは、 3 行目で zeibetsu は 2000 に変わります。
4 行目の zeikomi は 2100 です。なぜなら、 3 行目の時点で zeibetsu の数字が代わってしまったので、 zeibetsu * 1.05 が 2000 * 1.05 になってしまったのです。
zeibetsu は 1000 でも 2000 でもある、ということにはならないのです。zeikomi も同様に、 1050 でも 2100 でもある、ということではありません。 4 行目の時点で 2100 に変わります。変わってしまうのです。
なので、これら zeibetsu zeikomi を変数といいます。
ちなみに、続く 5 行目で zeibetsu は 3000 に変わり、 6 行目の zeikomi は 3150 となります。


では、"上から順に" ルールはそのままに、本屋に戻しましょう。

税別価格 = 1000;
税込価格 = 税別価格 * 1.05;
税別価格 = 2000;
税込価格 = 税別価格 * 1.05;
税別価格 = 3000;
税込価格 = 税別価格 * 1.05;

上から下へ順に計算していくと、最終的には、税別価格は 3000 、税込価格は 3150 になっています。
なので、最後に次の計算を追加すると

税込価格5冊分 = 税込価格 * 5;

税込価格5冊分は 3150 * 5 で 15750 になります。

計算式に名前をつける (関数)

税込価格の計算は終わりました。次のステップへ行きましょう。


税込価格、税別価格というのは随分と大雑把です。
本の価格まわりは、細かくみると以下のような関係でした。

基本販売価格 = 仕入価格 + マージン
税別販売価格 = 基本販売価格 - セール割引
税込販売価格 = 税別販売価格 + 消費税

そして、本の仕入価格は次の通りです。

本の名前   仕入価格
カロリーメイトのススメ   ¥800
マン・イン・メガネ   ¥1,600
働きアリのデスマーチ   ¥2,400

では、『カロリーメイトのススメ』の税込販売価格を計算してみましょう。
マージンは 仕入価格の 25% 、セール割引が 500 円、消費税率が 5% とします。

仕入価格     = 800
マージン率   = 0.25
セール割引   = 500
消費税率     = 0.05
マージン     = 仕入価格 * マージン率
基本販売価格 = 仕入価格 + マージン
税別販売価格 = 基本販売価格 - セール割引
消費税       = 税別販売価格 * 消費税率
税込販売価格 = 税別販売価格 + 消費税

いきなり複雑になった気もしますが、ちゃんと解けますね。

仕入価格     = 800
マージン率   = 0.25
セール割引   = 500
消費税率     = 0.05
マージン     = 仕入価格 * マージン率     = 800 * 0.25 = 200
基本販売価格 = 仕入価格 + マージン       = 800 + 200  = 1000
税別販売価格 = 基本販売価格 - セール割引 = 1000 - 500 = 500
消費税       = 税別販売価格 * 消費税率   = 500 * 0.05 = 25
税込販売価格 = 税別販売価格 + 消費税     = 500 + 25   = 525

カロリーメイトのススメ』の税込み販売価格は ¥525 になりました。
では続いて他の 2 冊も計算してみましょうか。

仕入価格     = 1600
マージン率   = 0.25
セール割引   = 500
消費税率     = 0.05
マージン     = 仕入価格 * マージン率
基本販売価格 = 仕入価格 + マージン
税別販売価格 = 基本販売価格 - セール割引
消費税       = 税別販売価格 * 消費税率
税込販売価格 = 税別販売価格 + 消費税

仕入価格     = 2400
マージン率   = 0.25
セール割引   = 500
消費税率     = 0.05
マージン     = 仕入価格 * マージン率
基本販売価格 = 仕入価格 + マージン
税別販売価格 = 基本販売価格 - セール割引
消費税       = 税別販売価格 * 消費税率
税込販売価格 = 税別販売価格 + 消費税

これを上から順に計算していくと、税込販売価格は ¥2625 になります。
でも正直、長すぎて嫌になりますね。


上の計算式を見てみると、変わっているのは仕入価格だけで、あとは同じ計算です。
これなら、同じ部分を一箇所にまとめてしまったほうが楽になります。
例えばこんな感じに。

仕入価格     = (共通でない)
マージン率   = 0.25
セール割引   = 500
消費税率     = 0.05
マージン     = 仕入価格 * マージン率
基本販売価格 = 仕入価格 + マージン
税別販売価格 = 基本販売価格 - セール割引
消費税       = 税別販売価格 * 消費税率
税込販売価格 = 税別販売価格 + 消費税

一つにまとめたからには、まとめたものの名前が必要です。
(『仕入価格〜税込販売価格の計算式』でもいいですが、長すぎで面倒です)
以降、この一連の計算を、『価格計算式』と呼ぶことにしましょう。


『価格計算式』は、ただそれだけでは計算できません。
なぜなら仕入価格が定まってないからです。

仕入価格さえ決まれば計算できるよ

仕入価格が必要だよ!


なので、『価格計算式』に仕入価格を教えてあげる必要があります。
こういうとき、プログラムでは『仕入価格は 800 だよ』ということを『価格計算式(800) 』という形で教えてあげます。
少し書き直してみましょう。

価格計算式
  仕入価格     = () の中身
  マージン率   = 0.25
  セール割引   = 500
  消費税率     = 0.05
  マージン     = 仕入価格 * マージン率
  基本販売価格 = 仕入価格 + マージン
  税別販売価格 = 基本販売価格 - セール割引
  消費税       = 税別販売価格 * 消費税率
  税込販売価格 = 税別販売価格 + 消費税

価格 = 価格計算式(800)
価格 = 価格計算式(1600)
価格 = 価格計算式(2400)

() の中に仕入価格を書くことで、『価格計算式』に仕入価格を教えてあげます。
仕入価格が決まれば『価格計算式』は計算できるようになりますので、ちゃんと税込販売価格を計算できるようになりました。
このまとめ方を "関数" といいます。


では、プログラムっぽく書いてみましょう。

function Kakaku_Keisan(Nakami)
{
  Shiire_Kakaku = Nakami;
  Margin_Ritsu  = 0.25;
  Sale_Waribiki = 500;
  Shouhi_Zeiritsu = 0.05;
  Margin        = Shiire_Kakaku * Margin_Ritsu;
  Kihon_Hanbai_Kakaku = Shiire_Kakaku + Margin;
  Zeibetsu_Hanbai_Kakaku = Kihon_Hanbai_Kakaku - Sale_Waribiki;
  Shouhi_Zei = Zeibetsu_Hanbai_Kakaku * Shouhi_Zeiritsu;
  Zeikomi_Hanbai_Kakaku = Zeibetsu_Hanbai_Kakaku + Shouhi_Zei;
  return Zeikomi_Hanbai_Kakaku;
}

Kakaku = Kakaku_Keisan(800);
Kakaku = Kakaku_Keisan(1600);
Kakaku = Kakaku_Keisan(2400);

これは実際に Javascript で動作するプログラムです。
(計算するだけなので何も表示されませんが)

function 名前(教えられたものの名前)
{
}

これが関数をつくっている部分です。
(教えられたものの名前) は、教えてもらった数字を表す変数です。
例えば

function Kakaku_Keisan(Nakami)
{
  Shiire_Kakaku = Nakami;
  ...(省略)
  Zeikomi_Hanbai_Kakaku = Zeibetsu_Hanbai_Kakaku + Shouhi_Zei;
  return Zeikomi_Hanbai_Kakaku;
}

Kakaku = Kakaku_Keisan(800);

のとき、 Nakami は 800 です。


また、関数の最後にある return は特別な意味があります。
プログラムは基本的に馬鹿です。
教えてもらわないと何も分かりません。
関数の中には Shiire_Kakaku や Margin_Ritsu 、 Zeikomi_Hanbai_Kakaku と、沢山の変数があります。
が、プログラムは、関数の計算式を全て計算し終わっても、
『じゃあどれが答えなの?』
っていうのが分かってません!
そんなわけで、『これが答えだよ』って return Zeikomi_Hanbai_Kakaku で教えてあげています。
これで、 Kakaku は 500 になりました。


長いので後でまとめよう。

*1:バグなんてない、全部仕様通りなんだ……