エンタープライズギークス (Enterprise Geeks)

企業システムの企画・開発に携わる技術者集団のブログです。開発言語やフレームワークなどアプリケーション開発に関する各種情報を発信しています。ウルシステムズのエンジニア有志が運営しています。

JavaScriptでLispインタープリターを作ろう(3) ~条件分岐「if」を導入~

前回の記事では、JavaScriptで記述した小さな四則演算インタープリターの実装を解説した。

この四則演算インタープリターは、電卓としてはうまく機能することが前回の解説で理解できたかと思う。しかし、このインタープリターには、プログラムを記述する際に必要となる条件分岐という概念が含まれていないため、プログラミング言語っぽさがない。今回は、この四則演算インタープリターに、条件分岐ifを導入し、よりプログラミング言語らしい言語に一歩近付ける。

条件分岐ifを導入するための改善はとても簡単だ。evaluate関数を以下のように変更するだけである。

var evaluate = function(x, env) {
  if (Array.isArray(x)) {
    if (x[0] === 'if') { // if というキーワードだった場合
      return String(evaluate(x[1], env)) !== 'false'
        ? evaluate(x[2], env)
        : evaluate(x[3], env);
    } else { // if ではない場合、今までどおりの処理を行う
      var exps = x.map(function(exp) {return evaluate(exp, env);});
      var proc = exps.shift();
      return proc.apply(null, exps);
    }
  } else {
    var y = env[x];
    return y !== undefined ? y : x;
  }
};

四則演算インタープリターからの変更点は次の通り。
これまではArray.isArray(x)trueだった場合、そのまま関数を実行していた。しかし今回は、配列の第1要素がifだった場合は特殊な処理を行うように変更した。

すなわち、配列の第1要素がifだった場合は配列の第2要素を評価し、その評価結果がtrueになった場合は配列の第3要素を評価し、そうでなければ第4要素を評価するようにしている。

このような処理を追加することにより、以下の様な記述が可能になる。

>> evaluate(['if', true, 1, 2], globalEnv);
1
>> evaluate(['if', false, 1, 2], globalEnv);
2

このように、配列の第二引数がtruefalseかによって、挙動が変えられるようになった。他の例も見てみよう。

// この例では ['+', 1, 2] が計算される
>> evaluate(['if', true, ['+', 1, 2], ['+', 2, 3]], globalEnv);
3
// この例では ['+', 2, 3] が計算される
>> evaluate(['if', false, ['+', 1, 2], ['+', 2, 3]], globalEnv);
5
// この例では ['+', 1, 2] が計算された後に 1 が足される
>> evaluate(['+', 1, ['if', true, ['+', 1, 2], ['+', 2, 3]]], globalEnv);
4

これらの例から、ifが正常に機能している事がお分かりいただけると思う。さて、「if」の条件がtrue/falseの固定値では面白く無いので、ifを有効活用するために、ライブラリーに関数を追加し、値の大小比較を行えるようにしてみる。また、JavaScriptのalertダイアログを表示する関数も追加し、処理状況を確認可能にする。

追加したのは、=,>,<,<=,>=,alertといった関数である。これらを追加したことにより、以下の様なコードも試せるようになる。

// ['mod', 9, 3] を計算すると 0 となり、ゼロとイコールであるので 1 が結果となる
>> evaluate(['if', ['=', 0, ['mod', 9, 3]], 1, 2], globalEnv);
1

条件分岐ifの導入に関する説明は以上だ。意外と簡単だったのではないだろうか。ifが導入されたことで、単純な電卓だった四則演算インタープリターが、一歩、プログラミング言語に近づいたと感じて頂ければ幸いである。

[近棟 稔]