EoPL reading (40) 1.3.1 Free and Bound Variables

Exercise.1-32

なんとなく Ex.1-31 の逆で良いカンジをイメージしてるんですがどうなる事やら。
とりあえず lambda 式が変換できるように、という事で例示されているナニを試験に盛り込んでおく。

(use gauche.test)

(add-load-path ".")
(load "un-lexical-address")

(test-start "un-lexical-address")
(test-section "un-lexical-address")

(test* "(un-lexical-address '(lambda (a) 
                               (lambda (b c) 
                                 ((: 1 0) (: 0 0) (: 0 1))))) 
         should return (lambda (a) (lambda (b c) (a b c)))"
       '(lambda (a) (lambda (b c) (a b c)))
       (un-lexical-address '(lambda (a) 
                               (lambda (b c) 
                                 ((: 1 0) (: 0 0) (: 0 1))))))

(test-end)

微妙にハードル高そげ。ガワだけ作った。

(define (un-lexical-address exp)
  (define (un-lexical-address-inner rslt dict l)
    (cond ((null? l) rslt)
	  ((symbol? l)
	   )
	  ((eqv? (car l) 'lambda)
	   )
	  (else
	   ))
    )
  (un-lexical-address-inner '() '() exp)
  )

どうしたものやら。
って、基本 symbol は表れない、を前提にしても良いのかな。てーコトはリストの car が : だったら symbol 扱いすりゃ良いのか。
と言いつつ適当にビートたけしが出てくる番組を見つつ (見てないけど)、Ex.1-31 を見ながら手続きをでっちあげたら上記の試験にパス。

(define (un-lexical-address exp)
  (define (un-lexical-address-inner rslt dict l)
    (cond ((null? l) rslt)
	  ((eqv? (car l) 'lambda)
	   (un-lexical-address-inner (append rslt `(lambda ,(cadr l)))
				     (cons (cadr l) dict) (cddr l))
	   )
	  (else
	   (if (eqv? (car l) ':)
	       (let f ((d 0) (dict dict))
		 (cond ((null? dict) #f)
		       ((eq? (cadr l) d)
			(let f-inner ((p 0) (dict (car dict)))
			  (if (eq? (caddr l) p)
			      (car dict)
			      (f-inner (+ p 1) (cdr dict)))))
		       (else
			(f (+ d 1) (cdr dict)))))
	       (let g ((rslt rslt) (l l))
		 (if (null? l) 
		     rslt
		     (g (append rslt (list (un-lexical-address-inner '()
								     dict
								     (car l))))
			(cdr l))))
	       )
	   ))
    )
  (un-lexical-address-inner '() '() exp)
  )

これは違う意味で微妙。試験は足りてないので別途。