SICPを読む上でよく見るメモ

ゼミのたびに「あの単語の意味ってなんだったっけ?」って事案が多発するので定義をまとめた記事を作ります。

適用順序評価と正規順序評価
  • 正規順序評価(normal-order evaluation)

  完全に展開してから簡約する。

  • 適用順序評価(applicative-order evaluation)

  引数を評価してから展開する。

displayとnewline

condの中でdisplayを複数使いたいときは次のようにする

(cond (condition?)
	(display hoge)
	(newline)
	)

次のようにすると怒られる

(cond (condition?)
	((display hoge)
	(newline))
	)

二つ目だとundefにundefを適用して死ぬ。一つ目は多分最後の値(ここだと(newline)によるundef)だけが返ってくるからセーフっぽい。

(define define 0)
(define define 0)

defineできなくなって詰む。

(文責:どりきゃす)

undefについて

( (hoge x) (huga y))
とかやって(hoge x)が(undefined)を返すと、(undefined (huga y))を実行しようとしてエラーが出て死ぬので
(define (undefToNil x)
nil)
とかを用意してやって
( (undefToNil (hoge x)) (huga y))とかしておくと(nil (huga y))とかになって美味しいみたいな話

putとget

tree-mapを使った実装

(define (key-compare a b) 0)

(define tm (make-tree-map key-compare))

(define (put op type item)
  (tree-map-put! tm (cons op type) item))

(define (get op type)
  (if (tree-map-exists? tm (cons op type))
      (tree-map-get tm (cons op type))
      #f))

ついでにattach-tag

(define (attach-tag type-tag contents)
  (cons type-tag contents ))

(define (type-tag datum)
  (if (pair? datum)
      (car datum)
      (error "Bad tagged datum: TYPE-TAG" datum )))

(define (contents datum)
  (if (pair? datum)
      (cdr datum)
      (error "Bad tagged datum: CONTENTS" datum )))

by pine

回路シミュレータで必要な関数定義
(define (half-adder a b s c)
  (let ((d (make-wire )) (e (make-wire )))
    (or-gate a b d)
    (and-gate a b c)
    (inverter c e)
    (and-gate d e s)
    'ok))

(define (full-adder a b c-in sum c-out)
  (let ((s (make-wire )) (c1 (make-wire )) (c2 (make-wire )))
    (half-adder b c-in s c1)
    (half-adder a s sum c2)
    (or-gate c1 c2 c-out)
    'ok))

(define (inverter input output)
  (define (invert-input)
    (let (( new-value (logical-not (get-signal input ))))
      (after-delay inverter-delay
                   (lambda () (set-signal! output new-value )))))
  (add-action! input invert-input) 'ok)
(define (logical-not s)
  (cond ((= s 0) 1)
        ((= s 1) 0)
        (else (error "Invalid signal" s))))

(define (and-gate a1 a2 output)
  (define (and-action-procedure)
    (let (( new-value
            (logical-and (get-signal a1) (get-signal a2))))
      (after-delay
       and-gate-delay
       (lambda () (set-signal! output new-value )))))
  (add-action! a1 and-action-procedure)
  (add-action! a2 and-action-procedure)
  'ok)

(define (logical-and s1 s2)
  (if (and (= s1 1) (= s2 1)) 1 0))

(define (or-gate a1 a2 output)
  (define (or-action-procedure)
    (let ((new-value (logical-or (get-signal a1) (get-signal a2))))
      (after-delay or-gate-delay (lambda () (set-signal! output new-value)))))
  (add-action! a1 or-action-procedure)
  (add-action! a2 or-action-procedure)
  'ok)

(define (logical-or s1 s2)
  (if (or (= s1 1) (= s2 1)) 1 0))

(define (make-wire)
  (let (( signal-value 0) (action-procedures '()))
    (define (set-my-signal! new-value)
      (if (not (= signal-value new-value ))
          (begin (set! signal-value new-value)
                 (call-each action-procedures ))
          'done ))
    (define (accept-action-procedure! proc)
      (set! action-procedures
            (cons proc action-procedures ))
      (proc ))
    (define (dispatch m)
      (cond ((eq? m 'get-signal) signal-value)
            ((eq? m 'set-signal!) set-my-signal!)
            ((eq? m 'add-action!) accept-action-procedure!)
            (else (error "Unknown operation: WIRE" m))))
    dispatch ))

(define (call-each procedures)
  (if (null? procedures)
      'done
      (begin ((car procedures ))
             (call-each (cdr procedures )))))

(define (get-signal wire) (wire 'get-signal ))
(define (set-signal! wire new-value)
  ((wire 'set-signal!) new-value ))
(define (add-action! wire action-procedure)
  ((wire 'add-action!) action-procedure ))

(define (after-delay delay action)
  (add-to-agenda! (+ delay (current-time the-agenda ))
                  action
                  the-agenda ))

(define (propagate)
  (if (empty-agenda? the-agenda)
      'done
      (let (( first-item (first-agenda-item the-agenda )))
        (first-item)
        (remove-first-agenda-item! the-agenda)
        (propagate ))))

(define (probe name wire)
  (add-action! wire
               (lambda ()
                 (newline)
                 (display name) (display " ")
                 (display (current-time the-agenda ))
                 (display " New-value = ")
                 (display (get-signal wire )))))

(define (make-agenda) (list 0))

(define the-agenda (make-agenda ))
(define inverter-delay 2)
(define and-gate-delay 3)
(define or-gate-delay 5)

(define (make-time-segment time queue)
  (cons time queue ))
(define (segment-time s) (car s))
(define (segment-queue s) (cdr s))

(define (current-time agenda) (car agenda ))
(define (set-current-time! agenda time)
  (set-car! agenda time ))
(define (segments agenda) (cdr agenda ))
(define (set-segments! agenda segments)
  (set-cdr! agenda segments ))
(define (first-segment agenda) (car (segments agenda )))
(define (rest-segments agenda) (cdr (segments agenda )))

(define (empty-agenda? agenda)
  (null? (segments agenda )))

(define (add-to-agenda! time action agenda)
  (define (belongs-before? segments)
    (or (null? segments)
        (< time (segment-time (car segments )))))
  (define (make-new-time-segment time action)
    (let ((q (make-queue )))
      (insert-queue! q action)
      (make-time-segment time q)))
  (define (add-to-segments! segments)
    (if (= (segment-time (car segments )) time)
        (insert-queue! (segment-queue (car segments ))
                       action)
        (let ((rest (cdr segments )))
          (if (belongs-before? rest)
              (set-cdr!
               segments
               (cons (make-new-time-segment time action)
                     (cdr segments )))
              (add-to-segments! rest )))))
  (let (( segments (segments agenda )))
    (if (belongs-before? segments)
        (set-segments!
         agenda
         (cons (make-new-time-segment time action)
               segments ))
        (add-to-segments! segments ))))
(define (remove-first-agenda-item! agenda)
  (let ((q (segment-queue (first-segment agenda ))))
    (delete-queue! q)
    (if (empty-queue? q)
        (set-segments! agenda (rest-segments agenda )))))

(define (first-agenda-item agenda)
  (if (empty-agenda? agenda)
      (error "Agenda is empty: FIRST-AGENDA-ITEM")
      (let (( first-seg (first-segment agenda )))
        (set-current-time! agenda
                           (segment-time first-seg ))
        (front-queue (segment-queue first-seg )))))

(define (make-queue) (cons '() '()))
(define (front-queue queue)
  (if (empty-queue? queue)
      (error "FRONT called with an empty queue" queue)
      (car (front-ptr queue ))))
(define (insert-queue! queue item)
  (let (( new-pair (cons item '())))
    (cond (( empty-queue? queue)
           (set-front-ptr! queue new-pair)
           (set-rear-ptr! queue new-pair)
           queue)
          (else
           (set-cdr! (rear-ptr queue) new-pair)
           (set-rear-ptr! queue new-pair)
           queue ))))
(define (delete-queue! queue)
  (cond (( empty-queue? queue)
         (error "DELETE! called with an empty queue" queue ))
        (else (set-front-ptr! queue (cdr (front-ptr queue )))
              queue )))
(define (empty-queue? queue)
  (null? (front-ptr queue )))
(define (front-ptr queue) (car queue ))
(define (rear-ptr queue) (cdr queue ))
(define (set-front-ptr! queue item)
  (set-car! queue item ))
(define (set-rear-ptr! queue item)
  (set-cdr! queue item ))
並列化

参考:
concurrency - implement parallel execute in scheme - Stack Overflow

(define (parallel-execute . procs)
  (map thread-wait
       (map (lambda (proc) (thread proc))
            procs)))

by tube


Scheme on Scheme

コードは https://github.com/ht918/sicp-zemi

chap4/environments.scm は環境まわりの関数。
chap4/eval.scm を使えば eval が動くはず。