#lang racket #| ; a->b ; (define-syntax-rule (implies a b) (or (not a) b)) (define lala empty) (equal? (implies #f #t) #t) (equal? (implies (cons? lala) (even? (first lala))) #t) |# (define-syntax-rule (swap a b) (let* {[tmp a]} (begin (set! a b) (set! b tmp)))) ;(define let* 20) (define tmp 5) (define b 99) (swap tmp b) b tmp #| ;; Shouldn't (swamp tmp b) expand to: (let* {[tmp tmp]} (begin (set! tmp b) (set! b tmp))) ;; But this wouldn't work?! ;; What really happens: ;; Racket's macro generator is smart enough to ;; tag any local variables as different from surrounging variables, ;; even if they have the same name: (let* {[tmp1 tmp]} (begin (set! tmp b) (set! b tmp1))) ;; We say sucha a macro is "hygienic" -- it ;; does not capture/introduce its own local variables ;; into the site where the macro is expanded. |# ;;;;; A need for reflection: ; Suppose we have ; (define-struct ship (x y dir)) (define-struct astr (x y size)) (define s (make-ship 17 23 90)) (define a (make-astr 7 123 17)) ; We'd like to have a reader that translated s.x a.size ; to: (get-field s x) => (ship-x s) (get-field a size) => (astr-size a) ; where get-field is a macro that generated the code (ship-x s) (astr-size s) ; ; (and of course, get-field should work with *any* struct made in the future, too). ; But in order for this to work, we need to know the name of the type of s: ; for that we need reflection.