2014年9月15日月曜日

開発環境

計算機プログラムの構造と解釈[第2版](ハロルド エイブルソン (著)、ジュリー サスマン (著)、ジェラルド・ジェイ サスマン (著)、Harold Abelson (原著)、Julie Sussman (原著)、Gerald Jay Sussman (原著)、和田 英一 (翻訳)、翔泳社、原書: Structure and Interpretation of Computer Programs (MIT Electrical Engineering and Computer Science)(SICP))の4(超言語的抽象)、4.1(超循環評価器)、4.1.6(内部定義)、問題 4.16.を解いてみる。

その他参考書籍

問題 4.16.

コード(BBEdit, Emacs)

sample16.scm

#!/usr/bin/env gosh
;; -*- coding: utf-8 -*-

;; a
(define (lookup-variable-value var env)
  (define (env-loop env)
    (define (scan vars vals)
      (cond ((null? vars)
             (env-loop (enclosing-environment env)))
            ((eq? var (car vars))
             (if (eq? *unassigned* (car vals))
                 (error "Unassigned variable" var)
                 (car vals)))
            (else (scan (cdr vars) (cdr vals))))))
  (if (eq? env the-empty-environment)
      (error "Unbound variable" var)
      (let ((frame (first-frame env)))
        (scan (frame-variables frame)
              (frame-values frame))))
  (env-loop env))
             
;; b
(define (scan-out-defines body)
  (define (scan-define body)
    (cond ((null? body) #f)
          ((definition? (car body)) #t)
          (scan-define (cdr body))))
  (define (define-vars body)
    (cond ((null? body) '())
          ((definition? (car body))
           (cons (definition-variable (car body))
                 (define-vars (cdr body))))
          (else (define-vars (cdr body)))))
  (define (define-vals body)
    (cond ((null? body) '())
          ((definition? (car body))
           (cons (definition-value (car body))
                 (define-vals (cdr body))))
          (else (define-vals (cdr body)))))
  (define (scan-body body)
    (cond ((null? body) '())
          ((not (pair? (car body)))
           (cons (car body) (scan-body (cdr body))))
          ((definition? (car body)) (scan-body (cdr body)))
          (else (cons (car body) (scan-body (cdr body))))))
  (if (scan-define body)
      (let ((vars (define-vars body))
            (vals (define-vals body))
            (body (scan-body body)))
        (cons 'let (append (map (lambda (var)
                                  (list var ''*unassigned*))
                                vars)
                           (map (lambda (var val)
                                  (list 'set! var val))
                                vars
                                vals)
                           body)))
      body))

;; c
;; make-procedureに組み込んだ方が、呼び出し回数が少なくて済むので優れている
(define (make-procedure parameters body env)
  (list 'procedure parameters (scan-out-defines body) env))

入出力結果(Terminal(gosh), REPL(Read, Eval, Print, Loop))

$ ./sample16.scm
$

0 コメント:

コメントを投稿