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