PasteRack.org
Paste # 83464
2020-04-03 12:46:18

Fork as a new paste.

Paste viewed 488 times.


Embed:

  1. #lang racket/base
  2.  
  3. (require (for-syntax racket/base
  4.                      syntax/parse))
  5.  
  6. ;; Note: This uses keywords -- #:else and #:let -- because that's
  7. ;; generally considered "more Rackety", makes it clear what is a macro
  8. ;; keyword as opposed to some other identifier.
  9.  
  10. ;; Note: This intentionally requires a final #:else clause -- whereas
  11. ;; official cond will let you omit it and the result will be #<void>,
  12. ;; which I think is unhelpful. However, this simple version doesn't
  13. ;; attempt to give you a good error message about omitting it.
  14.  
  15. (define-syntax (-cond stx)
  16.   (syntax-parse stx
  17.     [(_ [#:let id:id rhs:expr] more:expr ...)
  18.      #'(let ([id rhs])
  19.          (-cond more ...))]
  20.     [(_ [#:else results:expr ...+])
  21.      #'(begin results ...)]
  22.     [(_ [test:expr results:expr ...+] more:expr ...+)
  23.      #'(if test
  24.            (begin results ...)
  25.            (-cond more ...))]))
  26.  
  27. (module+ test
  28.   (require rackunit)
  29.  
  30.   (check-equal? (-cond [#f 0]
  31.                        [#:else 42])
  32.                 42)
  33.  
  34.   (check-equal? (-cond [#t 42]
  35.                        [#:else 0])
  36.                 42)
  37.  
  38.   (check-equal? (-cond [#f 0]
  39.                        [#:else 42])
  40.                 42)
  41.  
  42.   (check-equal? (-cond [#f 0]
  43.                        [#f 1]
  44.                        [#:let foo 42]
  45.                        [#t foo]
  46.                        [#:else 0])
  47.                 42)
  48.  
  49.   (check-equal? (-cond [#f 0]
  50.                        [#f 1]
  51.                        [#:let foo 42]
  52.                        [#f 2]
  53.                        [#:else foo])
  54.                 42))

=>