destructure.scm 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees
  3. ; This is a destructuring version of LET.
  4. ; (DESTRUCTURE ((<pattern> <expression>) ...) body ...)
  5. ; The patterns can be:
  6. ; identifiers, which are bound to the corresponding part of the value
  7. ; lists of patterns (including dotted pairs)
  8. ; vectors of patterns
  9. ;
  10. ; Bug (?): (destructure (((a) '(1 2))) ...) works. The code does not check
  11. ; to see if there are more elements than the minimum number required.
  12. (define-syntax destructure
  13. (lambda (form rename compare)
  14. (let ((specs (cadr form))
  15. (body (cddr form))
  16. (%car (rename 'car))
  17. (%cdr (rename 'cdr))
  18. (%vref (rename 'vector-ref))
  19. (%let* (rename 'let*))
  20. (gensym (lambda (i)
  21. (rename (string->symbol
  22. (string-append "x" (number->string i))))))
  23. (atom? (lambda (x) (not (pair? x)))))
  24. (letrec ((expand-pattern
  25. (lambda (pattern value i)
  26. (cond ((or (not pattern) (null? pattern))
  27. '())
  28. ((vector? pattern)
  29. (let ((xvalue (if (atom? value)
  30. value
  31. (gensym i))))
  32. `(,@(if (eq? value xvalue) '() `((,xvalue ,value)))
  33. ,@(expand-vector pattern xvalue i))))
  34. ((atom? pattern)
  35. `((,pattern ,value)))
  36. (else
  37. (let ((xvalue (if (atom? value)
  38. value
  39. (gensym i))))
  40. `(,@(if (eq? value xvalue) '() `((,xvalue ,value)))
  41. ,@(expand-pattern (car pattern)
  42. `(,%car ,xvalue)
  43. (+ i 1))
  44. ,@(if (null? (cdr pattern))
  45. '()
  46. (expand-pattern (cdr pattern)
  47. `(,%cdr ,xvalue)
  48. (+ i 1)))))))))
  49. (expand-vector
  50. (lambda (vec xvalue i)
  51. (do ((j (- (vector-length vec) 1) (- j 1))
  52. (ps '() (append (expand-pattern (vector-ref vec j)
  53. `(,%vref ,xvalue ,j)
  54. (+ i 1))
  55. ps)))
  56. ((< j 0) ps)))))
  57. (do ((specs specs (cdr specs))
  58. (res '() (append (expand-pattern (caar specs) (cadar specs) 0)
  59. res)))
  60. ((null? specs)
  61. `(,%let* ,res . ,body)))))))