Chapter 4, Metalinguistic Abstraction

Exercise 4.13


I am somewhat confused with the naming of special form make-unbound!. Till now we used make- prefix to build a special form like we used make-if to convert cond to if.

So, I am hoping that author meant to build a special form make-unbound like we have define and if instead of make-if kind of procedure.

With this assumption, I think it would be better to follow the earlier naming, so I will be calling this special form as unbound!. Please tell what do you think? Did I missed anything?

I think one who can bind can also unbind. When one defines a variable it ofcourse gets defined in the current environment, so when one unbinds a variable it must also be for the current environment.

Apart from ownership, other things that are not specified in the problem is about the implementation - whether we just unset the point thus leaving a hole where variable is stored or should we also shift all the variables to not leave any holes.

I think both implmentation have pros and cons. As of now I have just unset the point thus leaving a hole. Perhaps a better strategy is maintaining a count of holes and when they reaches a threshold then shifting or creating a new without holes.

Here goes my solution:

(I built on top of the previous solutions. In last exercise I build find-pair it uses the same procedure.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
;;add following line in eval:
((unbound!? exp) (eval-unbound! exp env))

(define (unbound!? exp)
  (tagged-list? exp 'unbound!))

(define (unbound!-variable-name exp)
  (if (symbol? (cadr exp))
	  (cadr exp)
	  (error "Unbound variable name is not a symbol" exp)))

(define (eval-unbound! exp env)
  (unbound-variable! (unbound!-variable-name exp) env))

(define (unbound-variable! var env)
  (let ((pair (find-pair var env)))
	(if pair
		(begin (set-car! pair '()) (set-cdr! pair '()))
		(error "Unbound variable" var))))

Now, a small test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
;;; M-Eval input:
(define x 5)

;;; M-Eval value:
ok

;;; M-Eval input:
x

;;; M-Eval value:
5

;;; M-Eval input:
(unbound! x)

;;; M-Eval value:
#!unspecific

;;; M-Eval input:
x
;Unbound variable x