EoPL reading (104) 2.3 Representation Strategies for Data Types

ええと、Figure 2.3 の試験を書いてから Exercise 2.15 に着手する方向で。
Figure 2.3 の一連の手続き定義が以下。

(define eopl:error error)

(define empty-env
  (lambda ()
    (lambda (sym)
      (eopl:error 'apply-env "No binding for ~s" sym))))

(define extend-env
  (lambda (syms vals env)
    (lambda (sym)
      (let ((pos (list-find-position sym syms)))
	(if (number? pos)
	    (list-ref vals pos)
	    (apply-env env sym))))))

(define apply-env
  (lambda (env sym)
    (env sym)))

(define list-find-position
  (lambda (sym los)
    (list-index (lambda (sym1) (eqv? sym1 sym)) los)))

(define list-index
  (lambda (pred ls)
    (cond ((null? ls) #f)
	  ((pred (car ls)) 0)
	  (else
	   (let ((list-index-r (list-index pred (cdr ls))))
	     (if (number? list-index-r)
		 (+ list-index-r 1)
		 #f))))))

まず、list-index 手続きの試験から検討。こんなカンジで OK ?

(use gauche.test)

(add-load-path ".")
(load "Fig2.3")

(test-start "list-index")
(test-section "list-index")
(test* "search '()"
       #f
       (list-index (lambda (sym) (eqv? sym 'a)) '()))
(test* "unmatch"
       #f
       (list-index (lambda (sym) #f) '(a b c)))
(test* "match"
       0
       (list-index (lambda (sym) (eqv? sym 'a)) '(a b c)))
(test* "match"
       2
       (list-index (lambda (sym) (eqv? sym 'c)) '(a b c)))
(test* "unmatch"
       #f
       (list-index (lambda (sym) (eqv? sym 'd)) '(a b c)))

(test-end)

ちなみに pred に (lambda (sym) 'a) をセットしたら 0 が戻ってきました。#f 以外は真と見做す模様。引き続き list-find-position 手続きの試験が以下。

(use gauche.test)

(add-load-path ".")
(load "Fig2.3")

(test-start "list-find-position")
(test-section "list-find-position")
(test* "unmatch"
       #f
       (list-find-position 'z '(a b c)))
(test* "match"
       0
       (list-find-position 'a '(a b c)))
(test* "match"
       1
       (list-find-position 'b '(a b c)))
(test* "match"
       2
       (list-find-position 'c '(a b c)))
(test* "match"
       #f
       (list-find-position 'd '(a b c)))

(test-end)

以降が微妙。

extend-env 凄いな。ぱっと見よく分からんかったのですが、探索失敗な処理

	    (apply-env env sym))))))

は extend する前の環境をナニしてるのか。ちょっと今日 NDK の makefile ニラんでたので scheme 脳が退化してるかも。単体試験になってないけど以下。

(use gauche.test)

(add-load-path ".")
(load "Fig2.3")

(test-start "extend-env")
(test-section "abnormal end")
(test* "apply empty-env"
       *test-error*
       (apply-env empty-env 'a))
(test* "search 'a from '(b c)"
       *test-error*
       (apply-env (extend-env '(b c) '(0 1) empty-env)
		  'a))
(test* "search 'z from '((a) (b c))"
       *test-error*
       (apply-env (extend-env '(a) '(0)
			      (extend-env '(b c) '(1 2) empty-env))
		  'z))
       
(test-section "normal end")
(test* "search 'a from '(a b)"
       0
       (apply-env (extend-env '(a b) '(0 1) empty-env)
		  'a))
(test* "search 'b from '(a b)"
       1
       (apply-env (extend-env '(a b) '(0 1) empty-env)
		  'b))
(test* "search 'c from '((a b) (c))"
       2
       (apply-env (extend-env '(a b) '(0 1)
			      (extend-env '(c) '(2) empty-env))
		  'c))

(test-end)

明日はこれを元にして本文も読みつつ 2.15 に着手予定。明後日は健康診断後に OSC 参加予定ッス。