SICP問題4.9
2010/03/17 while?の定義の部分が間違ってたので修正
do,for,while,untilといった反復構造を設計し、その使用例を示し、それを導出された式としてどう実装するのか示せということだが、Schemeのdo構文が分かりづらいのでwhileの実装を考えてみる
(while <predicate> <body>)
という感じで、
使い方はこんな感じ
(let ((n 10) (i 0) (counter 0)) (while (< counter n) (begin (set! counter (+ counter 1)) (set! i (+ i counter)))) (display i)) ; 55
これは
(let ((n 10) (i 0) (counter 0)) (let loop () (if (< counter n) (begin (begin (set! counter (+ counter 1)) (set! i (+ i counter))) (loop)))) (display i)) ; 55
に書き直しが可能なので以下のように実装。
(define (while? exp) (tagged-list? exp 'while)) (define (while-predicate exp) (cadr exp)) (define (while-body exp) (cddr exp)) (define (make-named-let name parameters body) (list 'let name parameters body)) (define (while->named-let exp) (make-named-let 'while-loop '() (make-if (while-predicate exp) (make-begin (list (car (while-body exp)) '(while-loop))) '()))) ; eval (define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp)) ((quoted? exp) (text-of-quotation exp)) ((assignment? exp) (eval-assignment exp env)) ((definition? exp) (eval-definition exp env)) ((if? exp) (eval-if exp env)) ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ((let? exp) (eval (let->combination exp) env)) ((let*? exp) (eval (let*->nested-lets exp) env)) ((while? exp) (eval (while->named-let exp) env)) ; 追加 ((begin? exp) (eval-sequence (begin-actions exp) env)) ((cond? exp) (eval (cond->if exp) env)) ((and? exp) (eval-and exp env)) ((or? exp) (eval-or exp env)) ((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env))) (else (error "Unknown expression type -- EVAL" exp))))