@uents blog

Code wins arguments.

SICP 読書ノート#43 - RubyでSchemeインタプリタをつくろう(2)

引き続きRubySchemeインタプリタを書き起こして行きます。

手続きの引数

引数expsにある式リストからひとつずつ式を取り出し評価したリストを返す。

def list_of_values(exps, env)
  if no_operands?(exps)
    nil
  else
    cons(_eval(first_operand(exps), env),
         list_of_values(rest_operand(exps), env))
  end
end

条件文

述語式の結果が真ならconsequent(結果)を、偽ならalternative(代替)を評価する。

def eval_if(exp, env)
  if true?(_eval(if_predicate(exp), env))
    _eval(if_consequent(exp), env)
  else
    _eval(if_alternative(exp), env)
  end
end

並び

applyで適用された手続きの本体bodyから取り出した一連の式を順次評価する。

def eval_sequence(exps, env)
  if last_exp?(exps)
    _eval(first_exp(exps), env)
  else
    _eval(first_exp(exps), env)
    eval_sequence(rest_exps(exps), env)
  end
end

代入と定義

代入(assignment)も定義(definition)のどちらも環境へ変数をセットするため、似たような実装になっている。

代入は環境から変数を探し出し、evalした結果をその変数に割り当てる。

def eval_assignment(exp, env)
  var = assignment_variable(exp)
  value = _eval(assignment_value(exp), env)
  set_variable_value!(var, value, env)
  :ok
end

定義は環境に新しい束縛を追加するはず。

def eval_definition(exp, env)
  var = definition_variable(exp)
  value = _eval(definition_value(exp), env)
  define_variable!(var, value, env)
  :ok
end

次回は「§4.1.2 式の表現」から。


※「SICP読書ノート」の目次はこちら