fork download
  1. ;; Clojure's when-let using Lisp-style macros.
  2.  
  3. (use-modules (language tree-il))
  4.  
  5. (define (display-macroexpand expr)
  6. (display (tree-il->scheme (macroexpand expr)))
  7. (newline))
  8.  
  9. ;; when-let.
  10.  
  11. (define-macro (when-let bindings . body)
  12. (unless (= (length bindings) 1)
  13. (error "call to when-let did not conform to spec"))
  14. `(let (,@bindings)
  15. (when ,(caar bindings)
  16. ,@body)))
  17.  
  18. (display-macroexpand '(when-let ((x (= 1 1))) x))
  19. (display-macroexpand '(when-let ((x (= 1 1))) x x))
  20. (display-macroexpand '(when-let ((x (= 1 1))) x (x (x))))
  21.  
  22. (when-let ((x #f))
  23. (format #t "!:<~S>~%" x))
  24. (when-let ((x #t))
  25. (format #t "t:<~S>~%" x))
  26. (when-let ((x (= 1 2)))
  27. (format #t "!:<~S>~%" x))
  28. (when-let ((x (= 1 1)))
  29. (format #t "t:<~S>~%" x))
  30. (when-let ((x (+ 1 1)))
  31. (format #t "2:<~S>~%" x))
  32.  
  33. ;; when-let using gensym (unnecessary).
  34. ;; @note The body needs access to the generated symbols.
  35.  
  36. (define (subst new old tree equal)
  37. (let loop ((tree tree))
  38. (cond
  39. ((equal tree old) new)
  40. ((pair? tree)
  41. (cons (loop (car tree))
  42. (loop (cdr tree))))
  43. (else tree))))
  44.  
  45. (define-macro (when-let bindings . body)
  46. (unless (= (length bindings) 1)
  47. (error "call to when-let did not conform to spec"))
  48. (let ((g (gensym)))
  49. `(let (,@(subst g (caar bindings) bindings eq?))
  50. (when ,g
  51. ,@(subst g (caar bindings) body eq?)))))
  52.  
  53. (display-macroexpand '(when-let ((x (= 1 1))) x))
  54. (display-macroexpand '(when-let ((x (= 1 1))) x x))
  55. (display-macroexpand '(when-let ((x (= 1 1))) x (x (x))))
  56.  
  57. (when-let ((x #f))
  58. (format #t "!:<~S>~%" x))
  59. (when-let ((x #t))
  60. (format #t "t:<~S>~%" x))
  61. (when-let ((x (= 1 2)))
  62. (format #t "!:<~S>~%" x))
  63. (when-let ((x (= 1 1)))
  64. (format #t "t:<~S>~%" x))
  65. (when-let ((x (+ 1 1)))
  66. (format #t "2:<~S>~%" x))
Success #stdin #stdout 0.02s 12192KB
stdin
Standard input is empty
stdout
(let ((x (= 1 1))) (if x x))
(let ((x (= 1 1))) (if x (begin x x)))
(let ((x (= 1 1))) (if x (begin x (x (x)))))
t:<#t>
t:<#t>
2:<2>
(let ((#{ g23}# (= 1 1))) (if #{ g23}# #{ g23}#))
(let ((#{ g24}# (= 1 1))) (if #{ g24}# (begin #{ g24}# #{ g24}#)))
(let ((#{ g25}# (= 1 1))) (if #{ g25}# (begin #{ g25}# (#{ g25}# (#{ g25}#)))))
t:<#t>
t:<#t>
2:<2>