#lang racket ; CS 251 macro examples (provide (all-defined-out)) ;; a cosmetic macro -- adds then, else (define-syntax my-if (syntax-rules (then else) [(my-if e1 then e2 else e3) (if e1 e2 e3)])) ;; a macro to replace an expression with another one (define-syntax comment-out (syntax-rules () [(comment-out ignore instead) instead])) ;;;;; some macro uses (define seven (my-if #t then 7 else 14)) ; SYNTAX ERROR: (define does-not-work (my-if #t then 7 then 9)) ; SYNTAX ERROR: (define does-not-work (my-if #t then 7 else else)) (define no-problem (comment-out (car null) #f)) ;;;;; more examples ;; a loop that executes body hi - lo times ;; notice use of local variables (define-syntax for (syntax-rules (to do) [(for lo to hi do body) (let ([l lo] [h hi]) (letrec ([loop (lambda (it) (if (> it h) #t (begin body (loop (+ it 1)))))]) (loop l)))])) ;; let2 allows up to two local bindings (with let* semantics) with fewer parentheses ;; than let* (define-syntax let2 (syntax-rules () [(let2 () body) body] [(let2 (var val) body) (let ([var val]) body)] [(let2 (var1 val1 var2 val2) body) (let ([var1 val1]) (let ([var2 val2]) body))])) ;; the special ... lets us take any number of arguments ;; Note: nothing prevents infinite code generation except ;; the macro definer being careful (define-syntax my-let* (syntax-rules () [(my-let* () body) body] [(my-let* ([var0 val0] [var-rest val-rest] ...) body) (let ([var0 val0]) (my-let* ([var-rest val-rest] ...) body))]))