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