;;; 61.ss -- SRFI 61 -- Jens Axel Soegaard -- 23 july 2005 ; This is an implementation of SRFI-61 "A more general cond clause". ; ; The implementation provides better error messages than the provided ; reference implementation. (module |61| mzscheme (provide (rename my-cond cond)) (define-syntax (non-spliceable-begin stx) (syntax-case stx () [(_ expr ...) #'(if #t (begin expr ...))])) (define-syntax (my-cond stx) (syntax-case stx () [(cond) (raise-syntax-error #f "expected a list of clauses after 'cond' but got nothing" stx)] [(cond clause ...) (let loop ([clauses #'(clause ...)]) (syntax-case clauses () [() #'(void)] [_ (with-syntax ([(clause . more-clauses) clauses]) (syntax-case #'clause (=> else) [(else expr1 expr2 ...) (if (null? (syntax-e #'more-clauses)) #'(non-spliceable-begin expr1 expr2 ...) (raise-syntax-error 'cond "found an 'else' clause that isn't the last clause in its 'cond' expression" #'clause))] [(test => expr) #`(let ([val test]) (if val (let ((proc expr)) #,(syntax/loc #'clause (proc val))) ; location: e.g. (cond (1 => 2)) #,(loop #'more-clauses)))] [(generator guard => receiver) #`(call-with-values (lambda () generator) (lambda vals (if #,(syntax/loc #'clause (apply guard vals)) ; location: e.g (cond (1 2 => 3)) #,(syntax/loc #'clause (apply receiver vals)) ; location: e.g (cond (1 + => 3)) #,(loop #'more-clauses))))] [(test expr1 expr2 ...) #`(if test (non-spliceable-begin expr1 expr2 ...) #,(loop #'more-clauses))] [_ (raise-syntax-error 'cond (string-append "a clause must have one of these forms ( ...), ( => )," "( => or (else ...) " ) #'clause)]))]))] [_ (raise-syntax-error #f "found a use of 'cond' that does not follow an open parenthesis" stx)])) )