Implementing Objects Through Macros
Despite their syntactic differences, functional and object-oriented programs are more similar than you probably think they are. What do objects do? They group together data and functions into one piece of data, and you access methods by sending messages to objects. Whereas in functional programs, we might write
;; A dillo is a (make-dillo number boolean) (define-struct dillo (length dead?)) ;; longer-than? : dillo number -> boolean ;; is dillo longer than given length (define (longer-than? adillo len) (> (dillo-length adillo) len)) ;; run-over : dillo -> dillo ;; return dead dillo one unit longer than given dillo (define (run-over adillo) (make-dillo (+ (dillo-length adillo) 1) true))
We could also have written this in object-style in Scheme using functions to support messages:
(define make-dillo-obj (lambda (length dead?) (lambda (message) (cond [(symbol=? message 'longer-than?) (lambda (len) (> length len))] [(symbol=? message 'run-over) (lambda () (make-dillo-obj (+ length 1) true))])))) (define d1 (make-dillo-obj 5 false)) ((d1 'longer-than?) 6) ((d1 'longer-than?) 5) (define d2 ((d1 'run-over))) ((d2 'longer-than?) 5)
While you may believe that this example has the spirit of objects, it certainly doesn't look very convincing. Your job is write macros that provide a better syntax for defining object-oriented classes in Scheme. Your macros should support the following alternative syntax:
(define dillo-class (class (initvars length dead?) (method longer-than? (len) (> length len)) (method run-over () (dillo-class (+ length 1) true)))) (define d3 (dillo-class 5 false)) (send d3 longer-than? 6) (send d3 longer-than? 5) (define d4 (send d1 run-over)) (send d4 longer-than? 5)
To do this, you should implement two macros, one for
class
and one for send
. Your macros should
allow someone to define a class with any number (including 0) of
initvars and any number (including 0) of methods. Your macros should
be such that running the two versions of the dillos code shown above
(the make-dillo-obj
version and the
dillo-class
version) with their sample interactions
should produce the same answers.
Macros for Checking Access Policies
A software company wants to develop a program to restrict the updates that its employees can make to code, documentation, and status reports. A set of company-defined access rules determine which employees can update which types of files. For example, the company might specify that
The company proposes the following language for writing down policies (this example captures the above set of 5 rules).
(define check-policy (policy-checker (programmer (read write) (code documentation)) (tester (read) (code)) (tester (write) (documentation)) (manager (read write) (reports)) (manager (read) (documentation)) (ceo (read write) (code documentation reports))))
Each policy specifies a program that can be used to check whether a particular job can perform an access to a certain kind of file. For example, the following interaction uses the policy defined above:
> (check-policy 'programmer 'write 'code) true > (check-policy 'programmer 'write 'reports) false
Write a macro for policy-checker
such that this
example and interaction works as shown. Your macro should be able to
support any policy of this general format (in other words, it should
allow different numbers of roles, rules, kinds of files, and kinds of
accesses). Note that you are not writing a macro for
check-policy
: in the example above,
check-policy
is the name given to the program produced by
the macro, so you can use it to check access permissions as shown in
the sample interaction.
Turn in a single file hwk5.ss or hwk5.scm containing your answers. Make sure that both students' names are in a comment at the top of the file.