destructure.scm 2.0 KB

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