source: project/wiki/eggref/4/list-bindings @ 29859

Last change on this file since 29859 was 29859, checked in by juergen, 8 years ago

list-bindings 1.6 and yasos 1.3.1

File size: 9.3 KB
Line 
1[[tags: egg]]
2[[toc:]]
3
4== list-bindings
5
6This module provides some binding constructs, including a version of Common
7Lisp's destructuring-bind but with a shorter name, bind, and - as applications -
8define-macro, let-macro and letrec-macro. In all the macros defined
9here, pat is a pattern, i.e. a nested lambda-list and pattern variables
10are the symbols of the pattern.
11
12Contrary to the bindings egg, destructuring is only done for
13list expressions, which is sufficient for low-level macros.
14
15=== Programming interface
16
17==== list-bindings
18
19<procedure>(list-bindings)</procedure>
20
21shows the list of exported symbols.
22
23==== bind
24
25<syntax>(bind pat xpr . body)</syntax>
26
27binds pattern variables of the pattern pat to subexpressions of the
28nested pseudolist expression xpr and executes body in this context.
29
30==== bind-lambda
31
32<syntax>(bind-lambda pat xpr . xprs)</syntax>
33
34combination of bind and lambda.
35
36==== bind-set!
37
38<syntax>(bind-set! pat xpr)</syntax>
39
40sets the pattern variables of the pattern pat to corresponding
41subexpressions of the nested pseudolist xpr.
42
43==== bind-define
44
45<syntax>(bind-define pat xpr)</syntax>
46
47defines the pattern variables of the pattern pat by setting them to
48corresponding subexpressions of the nested pseudolist xpr.
49
50==== bind-let*
51
52<syntax>(bind-let* ((pat xpr) ...) . body)</syntax>
53
54binds pattern variables of the pattern pat to corresponding
55subexpressions of the nested pseudolist expression xpr ... in sequence
56and executes body in this context.
57
58==== bind-let
59
60<syntax>(bind-let ((pat xpr) ...) . body)</syntax>
61
62binds pattern variables of the pattern pat to corresponding
63subexpressions of the nested pseudolist expression xpr ... in parallel
64and executes body in this context.
65
66==== bindable?
67
68<syntax>(bindable? pat)</syntax>
69
70returns a predicate which checks, if its only list argument matches
71the patterns pat.
72
73====  bind-case
74
75<syntax>(bind-case xpr clause . clauses)</syntax>
76
77where xpr is a nested pseudolist expression and each clause is of the form
78(pat . body), with pat a pattern.
79
80Matches xpr against each pattern pat in sequence, binds the pattern
81variables of the first matching pat to correspondings subexpressions of
82xpr and executes the corresponding body in this context.
83
84==== bind-case-lambda
85
86<syntax>(bind-case-lambda (pat xpr . xprs) ...)</syntax>
87
88combination of bind-case and lambda.
89
90==== bind/cc
91
92<syntax>(bind/cc cont . body)</syntax>
93
94syntactic sugar for call-with-current-continuation. Captures the current
95contiunuation, binds it to cont and evaluates the body in
96this context.
97
98==== define-macro
99
100<syntax>(define-macro (name . args) (renaming (prefix .  prefixed-identifiers) (comparing keyword-predicate body)))</syntax>
101<syntax>(define-macro (name . args) (renaming (prefix .  prefixed-identifiers) body))</syntax>
102<syntax>(define-macro (name . args) (injecting identifiers (comparing keyword-predicates body)))</syntax>
103<syntax>(define-macro (name . args) (injecting identifiers body))</syntax>
104<syntax>(define-macro (name . args) (comparing keyword-predicate body))</syntax>
105<syntax>(define-macro (name . args) body)</syntax>
106         
107where renaming, injecting and comparing are auxiliary keywords,
108prefixed-identifiers is a list, where all of its items share the same prefix,
109identifiers is a list,
110keyword-predicates is either null or of the form (suffix . suffixed-keywords),
111suffixed-keywords is a list, where all of its items share the same suffix.
112
113
114Simplifies implicit-renaming macros by destructuring
115the macro-code automatically.
116The defined macro is either implicit- or explicit-renaming
117depending on the chosen keyword injecting or renaming.
118The macro either provides identifiers bound to itself injected or
119prefixed-identifiers bound to itself with the prefixed stripped and
120renamed.
121Moreover the macro provides keyword-predicates, suffixed-keywords, to
122check if a symbol compares to the keyword-predicate's name with its
123suffix stripped.
124The short-hand versions simply add the missing clauses with empty lists,
125where a missing injecting or renaming clause is interpreted as
126injecting.
127
128==== let-macro
129
130<syntax>(let-macro ((macro-code macro-body) ...) . body)</syntax>
131
132defines macros with macro-code and macro-body ... in parallel and
133exectues body in this context.
134
135==== letrec-macro
136
137<syntax>(letrec-macro ((macro-code macro-body) ...) . body)</syntax>
138
139defines macros with macro-code and macro-body ... recursively and
140exectues body in this context.
141
142=== Requirements
143
144None
145
146=== Examples
147
148<enscript highlight=scheme>
149
150(use list-bindings)
151
152(bind a 1 a) ; -> 1
153(bind (a b) '(1 2)  (list a b)) ; -> '(1 2)
154(bind (x y z w) '(1 2 3 4) (list x y z w)) ; -> '(1 2 3 4)
155(bind (x (y (z . u) . v) . w)
156        '(1 (2 (3 4) 5) 6)
157        (list x y z u v w)) ; -> '(1 2 3 (4) (5) (6))
158((bind-lambda (a (b . c) . d) (list a b c d))
159 '(1 (20 30 40) 2 3)) ; -> '(1 20 (30 40) (2 3))
160(bind-let* (((a b) '(1 2)) ((x . y) '(3))) (list a b x y))
161  ; -> '(1 2 3 ())
162(bind-let* (((a b) '(1 2)) ((x . y) (list a))) (list a b x y))
163  ; -> '(1 2 1 ())
164(bind-let (((a b) '(1 2)) ((x . y) '(3 4 4))) (list a b x y))
165  ; -> '(1 2 3 (4 4))
166(bind-case '(1 (2 3))
167        ((x (y z)) (list x y z))
168        ((x (y . z)) (list x y z))
169        ((x y) (list x y))) ; -> '(1 2 3)
170(bind-case '(1 (2 3))
171        ((x (y . z)) (list x y z))
172        ((x y) (list x y))
173        ((x (y z)) (list x y z))) ; -> '(1 2 (3)))
174(bind-case '(1 (2 3))
175        ((x y) (list x y))
176        ((x (y . z)) (list x y z))
177        ((x (y z)) (list x y z))) ; -> '(1 (2 3))
178(bind-case '(1 (2 . 3))
179        ((x y) (list x y))
180        ((x (y . z)) (list x y z))
181        ((x (y z)) (list x y z))) ; -> '(1 (2 . 3))
182((bind-case-lambda
183        ((a (b . c) . d) (list a b c d))
184        ((e . f) (list e f)))
185 '(1 2 3 4 5)) ; -> '(1 (2 3 4 5))
186(letrec (
187        (my-map
188                (lambda (fn lst)
189                        (bind-case lst
190                                (() '())
191                                ((x . xs) (cons (fn x) (map fn xs))))))
192        )
193        (my-map add1 '(1 2 3))) ; -> '(2 3 4)
194((bindable? (a b)) '(1 2)) ; -> #t
195((bindable? (a . b)) '(1)) ; -> #t
196((bindable? (x)) '(name 1)) ;-> #f
197((bindable? (_ x)) '(name 1)) ; -> #t
198((bindable? (_ x)) '(name 1 2)) ;-> #f
199(begin
200  (bind-set! (a (b . c)) '(1 (2)))
201  (list a b c)) ;-> '(1 2 ())
202(begin
203  (bind-define (push top pop)
204    (let ((state '()))
205      (list
206        (lambda (arg) (set! state (cons arg state)))
207        (lambda () (car state))
208        (lambda () (set! state (cdr state))))))
209  (push 3)
210  (push 5)
211  (top)) ; -> 5
212 
213(define-er-macro (efreeze xpr)
214        (renaming (% %lambda)
215                (comparing ()
216                        `(,%lambda () ,xpr))))
217((efreeze 3)) ; -> 3
218(define-macro (ifreeze xpr)
219        `(lambda () ,xpr))
220((ifreeze 5)) ; -> 5
221(define-macro (alambda args xpr . xprs)
222        (injecting (self)
223                `(letrec ((,self (lambda ,args ,xpr ,@xprs)))
224                         ,self)))
225(define ! (alambda (n) (if (zero? n) 1 (* n (self (- n 1))))))
226(! 5) ; -> 120
227(define-macro (foo pair)
228        (comparing (? bar?) `(if ,(bar? (car pair)) ,@(cdr pair) 'unchecked)))
229(foo (bar 'checked)) ; -> 'checked
230(foo (baz 'checked)) ; -> 'unchecked)
231(define-macro (baz pair)
232        (renaming (% %if)
233                (comparing (? bar?)
234                        `(,%if ,(bar? (car pair)) ,@(cdr pair) 'unchecked))))
235(baz (bar 'checked)) ; -> 'checked
236(baz (foo 'checked)) ; -> 'unchecked
237(define-macro (swap! x y)
238  `(let ((tmp ,x)) (set! ,x ,y) (set! ,y tmp)))
239(let ((x 'x) (y 'y)) (swap! x y) (list x y))
240  ; -> '(y x)
241(letrec-macro (((ifreeze xpr) `(lambda () ,xpr))
242                                                         ((efreeze xpr)
243                                                                (renaming (% %lambda)
244                                                                 `(,%lambda () ,xpr))))
245 ((efreeze ((ifreeze 3)))))
246 ; -> 3
247(let-macro (((ifreeze xpr) `(lambda () ,xpr))
248                                                ((efreeze xpr)
249                                                 (renaming (% %lambda)
250                                                        `(,%lambda () ,xpr))))
251  (list ((efreeze 3)) ((ifreeze 5))))
252  ; -> '(3 5)
253
254</enscript>
255
256== Last update
257
258Oct 06, 2013
259
260== Author
261
262[[/users/juergen-lorenz|Juergen Lorenz]]
263
264== License
265
266 Copyright (c) 2011-2013, Juergen Lorenz
267 All rights reserved.
268
269 Redistribution and use in source and binary forms, with or without
270 modification, are permitted provided that the following conditions are
271 met:
272 
273 Redistributions of source code must retain the above copyright
274 notice, this list of conditions and the following disclaimer.
275 
276 Redistributions in binary form must reproduce the above copyright
277 notice, this list of conditions and the following disclaimer in the
278 documentation and/or other materials provided with the distribution.
279 Neither the name of the author nor the names of its contributors may be
280 used to endorse or promote products derived from this software without
281 specific prior written permission.
282   
283 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
284 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
285 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
286 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
287 HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
288 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
289 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
290 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
291 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
292 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
293 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
294
295== Version History
296
297; 1.6 : bind-lambda and bind-case-lambda added
298; 1.5 : bind-set! and bind-define added, code partially rewritten
299; 1.4 : let-macro and letrec-macro added
300; 1.3 : define-macro now incorporates define-ir-macro and define-er-macro, which are no longer exported
301; 1.2 : define-macro added
302; 1.1 : bind-let and bind-let* added
303; 1.0 : initial import
Note: See TracBrowser for help on using the repository browser.