CS 2135 Homework 5: Macros

Due: October 2 (Thursday) at 11:59pm via turnin (assignment name hw5).

Assignment Goals


The Assignment

  1. Improving the Animation Language

    We want to use macros to improve the syntax of the animation language from lab 4. In particular, we would like to be able to write down animations using a notation like the following:

    (define program1
      (animation circle : (10 10) radius 5 dir (-3 4)
                 (make-move 5)
                 (make-scale 2)
                 (make-redirect 4 9)))
    
    (define program2
      (animation rect : (20 40) width 7 height 15 dir (1 9)
                 (make-move 9)))
    

    Define a macro animation that converts the above examples into the language of animations defined in lab 4. Use your code from lab4 to make sure that your basic interpreter still works with the new language (you don't need to show us that it works in what you turn in, but you should test it that way).

  2. 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. Consider the following programs over dillos:

    ;; 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 nested functions. The first lambda takes in the initialization arguments for the dillo-class. The second lambda takes a message that requests a particular service (method) for the object and returns the code for the requested method. The interaction shows how to use the resulting class and object:

    (define make-dillo-obj
      (lambda (length dead?)
        (lambda (service)
          (cond [(symbol=? service 'longer-than?) 
                 (lambda (len) (> length len))]
                [(symbol=? service '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 and using object-oriented classes. 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 (send is what calls methods). Your macros should be such that running the two versions of macros code (the make-dillo-obj version and the dillo-class version, with their sample interactions given above) should produce the same answers. Your macro should support classes with any number of initialization variables (0 or more) and any number of methods (1 or more).

    (For what it's worth, this example helps demonstrate that objects are essentially just another form of functions, at least at a conceptual level. You could extend the example and the macro to handle inheritence and other OO constructs in a straightforward manner. This doesn't mean that you implement a language like Java by turning objects into functions; it just means that the issues that arise when implementing one often arise in the other. Despite the syntactic differences, Java is actually much more like Scheme than like C++ in terms of how it operates.)

What to Turn In

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.


Back to the Assignments page