srfi-11.scm 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. ;;; srfi-11.scm --- let-values and let*-values
  2. ;; Copyright (C) 2000, 2001, 2002, 2004, 2006, 2009 Free Software Foundation, Inc.
  3. ;;
  4. ;; This library is free software; you can redistribute it and/or
  5. ;; modify it under the terms of the GNU Lesser General Public
  6. ;; License as published by the Free Software Foundation; either
  7. ;; version 3 of the License, or (at your option) any later version.
  8. ;;
  9. ;; This library is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Lesser General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Lesser General Public
  15. ;; License along with this library; if not, write to the Free Software
  16. ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;; Commentary:
  18. ;; This module exports two syntax forms: let-values and let*-values.
  19. ;;
  20. ;; Sample usage:
  21. ;;
  22. ;; (let-values (((x y . z) (foo a b))
  23. ;; ((p q) (bar c)))
  24. ;; (baz x y z p q))
  25. ;;
  26. ;; This binds `x' and `y' to the first to values returned by `foo',
  27. ;; `z' to the rest of the values from `foo', and `p' and `q' to the
  28. ;; values returned by `bar'. All of these are available to `baz'.
  29. ;;
  30. ;; let*-values : let-values :: let* : let
  31. ;;
  32. ;; This module is fully documented in the Guile Reference Manual.
  33. ;;; Code:
  34. (define-module (srfi srfi-11)
  35. :export-syntax (let-values let*-values))
  36. (cond-expand-provide (current-module) '(srfi-11))
  37. ;;;;;;;;;;;;;;
  38. ;; let-values
  39. ;;
  40. ;; Current approach is to translate
  41. ;;
  42. ;; (let-values (((x y . z) (foo a b))
  43. ;; ((p q) (bar c)))
  44. ;; (baz x y z p q))
  45. ;;
  46. ;; into
  47. ;;
  48. ;; (call-with-values (lambda () (foo a b))
  49. ;; (lambda (<tmp-x> <tmp-y> . <tmp-z>)
  50. ;; (call-with-values (lambda () (bar c))
  51. ;; (lambda (<tmp-p> <tmp-q>)
  52. ;; (let ((x <tmp-x>)
  53. ;; (y <tmp-y>)
  54. ;; (z <tmp-z>)
  55. ;; (p <tmp-p>)
  56. ;; (q <tmp-q>))
  57. ;; (baz x y z p q))))))
  58. ;; We could really use quasisyntax here...
  59. (define-syntax let-values
  60. (lambda (x)
  61. (syntax-case x ()
  62. ((_ ((binds exp)) b0 b1 ...)
  63. (syntax (call-with-values (lambda () exp)
  64. (lambda binds b0 b1 ...))))
  65. ((_ (clause ...) b0 b1 ...)
  66. (let lp ((clauses (syntax (clause ...)))
  67. (ids '())
  68. (tmps '()))
  69. (if (null? clauses)
  70. (with-syntax (((id ...) ids)
  71. ((tmp ...) tmps))
  72. (syntax (let ((id tmp) ...)
  73. b0 b1 ...)))
  74. (syntax-case (car clauses) ()
  75. (((var ...) exp)
  76. (with-syntax (((new-tmp ...) (generate-temporaries
  77. (syntax (var ...))))
  78. ((id ...) ids)
  79. ((tmp ...) tmps))
  80. (with-syntax ((inner (lp (cdr clauses)
  81. (syntax (var ... id ...))
  82. (syntax (new-tmp ... tmp ...)))))
  83. (syntax (call-with-values (lambda () exp)
  84. (lambda (new-tmp ...) inner))))))
  85. ((vars exp)
  86. (with-syntax ((((new-tmp . new-var) ...)
  87. (let lp ((vars (syntax vars)))
  88. (syntax-case vars ()
  89. ((id . rest)
  90. (acons (syntax id)
  91. (car
  92. (generate-temporaries (syntax (id))))
  93. (lp (syntax rest))))
  94. (id (acons (syntax id)
  95. (car
  96. (generate-temporaries (syntax (id))))
  97. '())))))
  98. ((id ...) ids)
  99. ((tmp ...) tmps))
  100. (with-syntax ((inner (lp (cdr clauses)
  101. (syntax (new-var ... id ...))
  102. (syntax (new-tmp ... tmp ...))))
  103. (args (let lp ((tmps (syntax (new-tmp ...))))
  104. (syntax-case tmps ()
  105. ((id) (syntax id))
  106. ((id . rest) (cons (syntax id)
  107. (lp (syntax rest))))))))
  108. (syntax (call-with-values (lambda () exp)
  109. (lambda args inner)))))))))))))
  110. ;;;;;;;;;;;;;;
  111. ;; let*-values
  112. ;;
  113. ;; Current approach is to translate
  114. ;;
  115. ;; (let*-values (((x y z) (foo a b))
  116. ;; ((p q) (bar c)))
  117. ;; (baz x y z p q))
  118. ;;
  119. ;; into
  120. ;;
  121. ;; (call-with-values (lambda () (foo a b))
  122. ;; (lambda (x y z)
  123. ;; (call-with-values (lambda (bar c))
  124. ;; (lambda (p q)
  125. ;; (baz x y z p q)))))
  126. (define-syntax let*-values
  127. (syntax-rules ()
  128. ((let*-values () body ...)
  129. (let () body ...))
  130. ((let*-values ((vars-1 binding-1) (vars-2 binding-2) ...) body ...)
  131. (call-with-values (lambda () binding-1)
  132. (lambda vars-1
  133. (let*-values ((vars-2 binding-2) ...)
  134. body ...))))))
  135. ;;; srfi-11.scm ends here