Changeset 39397 in project
- Timestamp:
- 11/27/20 17:47:10 (5 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
wiki/eggref/5/bindings
r38813 r39397 16 16 pattern and can be easily enhanced to accept other sequence types as 17 17 well, vectors, strings, arrays, or what have you. All this sequence 18 types can be nested and mixed as you need it. This flexibility is made 19 possible by one generic function, bind-listify*, which can add three 20 (or four) procedures, seq?, seq-car, seq-cdr (and possibly seq-null?) 21 to its local database and thus supplying support for a new sequence type. 22 23 The fundamental bind macro is given in two forms, whith and without a 24 body. The former is a variant of Common Lisp's destructuring-bind, the 25 latter simply set!s pattern variables to the corresponding sequence 26 values. 18 types can be nested and mixed as you need it. 19 20 This version uses the sequence routines from simple-sequences and is 21 based again on Paul Graham's dbind (On Lisp, p. 232), a version of 22 Common Lisp's destructuring-bind. 23 24 But this version of dbind supports setters as well, using dbind without 25 body. The reason to put it all in one huge macro is, that both variants 26 use a common set of subroutines, which are implemented within the macro 27 body. I could have put it into a helper module to be imported by syntax, 28 but this subroutines are without interest outside of dbind. 29 30 Other enhancements include length checks of sequences, a wildcard, _, which 31 matches everything and binds nothing, literals, which match only 32 themselfs but can't of course be bound, and dots, which are extensions of 33 ellipses: two dots accept zero or one items of the same shape as the 34 nested list to its left, and four dots accept only non-empty nested 35 lists. 36 37 Note, that dbind is not exported, bind and bind! are exported instead. 27 38 28 39 <macro>(bind pat seq xpr . xprs)</macro> 29 <macro>(bind pat seq)</macro>40 <macro>(bind! pat seq)</macro> 30 41 31 42 Here, a pattern, pat, is either … … 36 47 * a pair of patterns. 37 48 38 where dotted lists (i.e list patterns followed by two, tree or four dots) 39 are new in version 4.0. 40 41 seq is a nested sequence expression, i.e. a mixture of pseudolists, 42 vectors and strings (after having added string and vector support to a 43 generic transformer procedure, bind-listify*). This transformer procedure 44 is used to transform seq into a nested list. 49 where dotted lists (i.e nested list patterns followed by two, tree or 50 four dots) are new since version 4.0, and seq is a nested sequence 51 expression, i.e. a mixture of pseudolists, vectors and strings. Other 52 sequence types can be added by means of sequence-db, which is reexported 53 from simple-sequences. 45 54 46 55 Patterns are used to control the destructuring of sequences, bind 47 pattern variables (i.e. symbols in pat except the wildcard, _, which 48 matches everything, but binds nothing) to matching subexpressions of seq 49 and check if literals in pat are equal to matching subexpressions in seq. 56 pattern variables to corresponding subexpressions of seq, controlling 57 their length and checking if literals match themselfs. Then either the 58 body is executed in this context, or the pattern variables are set! to 59 the values of the corresponding subexpression. 50 60 Since the wildcard binds nothing, it can appear multiple times in the 51 61 same macro. 52 62 53 Dots might not only follow patterns but also expressions.54 Their meaning is55 56 * two dots: the expression to the left appears zero or one times,57 * three dots: zero or many times,58 * four dots: one or many times.59 60 63 === Documentation 64 65 ==== sequence-db 66 67 <procedure>(sequence-db)</procedure> 68 <procedure>(sequence-db seq)</procedure> 69 <procedure>(sequence-db seq? seq-length seq-ref seq-tail seq-maker . pos?)</procedure> 70 71 database processing: 72 the first resets the database to the standard with 73 lists, pairs, vectors and strings, 74 the second returns the vector of handlers as well as the discriminator, 75 the third adds a new database record either at the end or before the 76 pos? discriminator. 77 A record cosists of a discriminator, seq?, and a vector with items 78 seq-lenth, seq-ref, seq-tail and seq-maker patterned after vectors. 79 Note, that the last record can handle atoms, albeit it is not a 80 sequence. 81 This routine is reexported from simple-sequences. 61 82 62 83 ==== bindings … … 67 88 such an exported symbol, respectively. 68 89 69 === Procedures70 71 ==== bind-listify*72 73 This is a generic procedure. It is closed over a local database which74 contains the necessary sequence versions of car and cdr and possibly75 null?76 77 <procedure>(bind-listify*)</procedure>78 79 resets the internal database for lists only.80 81 <procedure>(bind-listify* seq)</procedure>82 83 returns the car-cdr-(respectivley car-cdr-null?)-list corresponding84 to seq's type.85 86 <procedure>(bind-listify* pat seq)</procedure>87 88 transforms a nested pseudolist with possible wildcard, literals89 and dotted lists to a an ordinary nested list without.90 91 <procedure>(bind-listify* seq? seq-car seq-cdr)</procedure>92 93 adds support for a new sequence type with predicate seq? and94 sequence variants of car and cdr to the internal database.95 96 <procedure>(bind-listify* seq? seq-car seq-cdr seq-null?)</procedure>97 98 the same as before but with a null?-variant of seq (if not given, it is99 constructed in bind's body).100 101 ==== vector-car102 103 <procedure>(vector-car vec)</procedure>104 105 vector-variant of car.106 107 ==== vector-cdr108 109 <procedure>(vector-cdr vec)</procedure>110 111 vector-variant of cdr.112 113 ==== vector-null?114 115 <procedure>(vector-null? vec)</procedure>116 117 vector-variant of null?.118 119 ==== string-car120 121 <procedure>(string-car vec)</procedure>122 123 string-variant of car.124 125 ==== string-cdr126 127 <procedure>(string-cdr vec)</procedure>128 129 string-variant of cdr.130 131 ==== string-null?132 133 <procedure>(string-null? vec)</procedure>134 135 string-variant of null?.136 137 === Binding macros138 139 ==== bind-list140 141 <macro>(bind-list pat lst . body)</macro>142 143 with body:144 binds pattern variables of of a nested list patern without wildcard, literals145 and dotted ends, pat,146 to corresponding values of a nested list147 and executes the body in this context.148 149 withoud body:150 set!s pattern variables of a nested list patern without wildcard, literals151 and dotted ends, pat, to corresponding values of a nested list.152 153 ==== bind-list!154 155 <macro>(bind-list! pat lst)</macro>156 <macro>(bind-list! pat)</macro>157 158 the former is an alias to bind-list without body,159 the latter is (bind-list! pat 'pat)160 161 90 ==== bind 162 91 163 <macro>(bind pat seq . body)</macro> 164 165 with body: 92 <macro>(bind pat seq xpr . xprs)</macro> 93 166 94 binds pattern variables of a nested patern, pat, possibly with wildcard, 167 literals and dotted ends 168 to corresponding values of a nested sequence, seq, possibly with 169 literals and dotted ends, and executes the body xpr .... in this context. 170 171 without body: 172 set!s pattern variables of a nested patern, pat, possibly with wildcard, 173 literals and dotted ends, 174 to corresponding values of a nested sequences, seq, possibly with literals 175 and dotted ends. 95 literals and dotted ends to corresponding values of a nested sequence, 96 seq, and executes the body xpr .... in this context. 176 97 177 98 ==== bind! … … 180 101 <macro>(bind! pat)</macro> 181 102 182 the former is an alias to bind without body, 183 the latter (bind! pat 'pat). 103 set!s pattern variables of a nested pattern, pat, possibly with 104 wildcard, literals and dotted ends, to corresponding values of a nested 105 sequences, seq. If no seq is given, 'pat is used. 184 106 185 107 ==== bind* … … 276 198 context. 277 199 278 ==== resolve-dots279 280 <macro>(resolve-dots . args)</macro>281 282 transforms the list args, which might contain lists followed by dots283 into a list without dots and the list to dots' left spliced into the284 result.285 286 200 === Requirements 287 201 288 None 202 simple-sequences 289 203 290 204 === Examples … … 292 206 <enscript highlight=scheme> 293 207 294 (import bindings checks) 295 296 ;; reset local database to nested pseudolists only 297 (bind-listify*) 298 299 ;; add vector and string support 300 (bind-listify* vector? vector-car vector-cdr) 301 (bind-listify* string? string-car string-cdr) 302 303 (bind-listify* 'a 1) ; -> '(1) 304 (bind-listify* '(a . as) #(1 2 3)) 305 ;-> '(1 #(2 3))) 306 (bind-listify* '(a (b #f) c) '(1 #(2 #f) 3)) 307 ;-> '(1 (2) 3)) 308 (bind-listify* '(a (b (c _ . cs) d) . es) #(1 (2 (3 30 300) 4) 50)) 309 ;-> '(1 (2 (3 (300)) 4) #(50))) 310 (bind-listify* '(a (_ b _) . c) '(1 #(20 30 40) 5)) 311 ;-> '(1 (30) (5))) 312 (bind-listify* '(x y as ... b c) '(-2 -1 1 2 3 40 50)) 313 ;-> '(-2 -1 (1 2 3) 40 50) 314 (bind-listify* '(x y as .. b c) '(-2 -1 40 50)) 315 ;-> '(-2 -1 () 40 50) 316 (bind-listify* '((as (bs cs)) ... d e) '((1 (2 3)) (10 (20 30)) 4 5)) 317 ;-> '(((1 10) ((2 20) (3 30))) 4 5) 318 319 (bind-list (x (y (z))) '(1 (2 (3))) (list x y z)) 320 ; -> '(1 2 3) 321 322 (let () 323 (bind-list! (u v w)) 324 (and (eq? u 'u) (eq? v 'v) (eq? w 'w))) 325 : -> #t 208 (import simple-sequences bindings checks) 326 209 327 210 (let ((stack #f) (push! #f) (pop! #f)) … … 353 236 ; -> 1 354 237 355 (bind (x y as .... d e) '(-1 0 1 2 3 4 5) (list x y as d e))356 ;-> '(-1 0 (1 2 3) 4 5)357 358 (bind (x y as .. d e) '(-1 0 4 5) (list x y as d e))359 ;-> '(-1 0 () 4 5)360 361 (bind ((as (bs cs)) ... d e)362 '((1 (2 3)) (10 (20 30)) 4 5)363 (list as bs cs d e))364 ;-> '((1 10) (2 20) (3 30) 4 5)238 (bind (x y as ....) '(-1 0 1 2 3 4) (list x y as)) 239 ;-> '(-1 0 (1 2 3)) 240 241 (bind (x y as ..) '(-1 0) (list x y as)) 242 ;-> '(-1 0 ()) 243 244 (bind ((as (bs cs)) ...) 245 '((1 (2 3)) (10 (20 30))) 246 (list as bs cs)) 247 ;-> '((1 10) (2 20) (3 30)) 365 248 366 249 (bind (x y z w) '(1 2 3 4) (list x y z w)) … … 516 399 517 400 (bind-case '(0 4) 518 ((a bs .... c) #f)519 ((a bs ... c) (list a bs c)))520 ;-> '(0 () 4)401 ((a bs ....) #f) 402 ((a bs ...) (list a bs))) 403 ;-> '(0 ()) 521 404 522 405 (bind-case '(0 1 2 3 4) 523 ((a bs .. c) #f)524 ((a bs ... c) (list a bs c)))525 ;-> '(0 (1 2 3) 4)406 ((a bs ..) #f) 407 ((a bs ...) (list a bs))) 408 ;-> '(0 (1 2 3)) 526 409 527 410 (bind-case '(0 #(1 (2 3)) 4) 528 ((a (bs (cs (ds))) .. e) #f)529 ((a (bs (cs ds)) .. e) (list a bs cs ds e)))530 ;-> '(0 (1) (2) (3) 4)411 ((a (bs (cs (ds))) ..) #f) 412 ((a (bs (cs ds)) ..) (list a bs cs ds))) 413 ;-> '(0 (1) (2) (3)) 531 414 532 415 (define (my-map fn lst) … … 581 464 ; -> '(1 20 #(30 40) (2 3) 4 (5 6)) 582 465 583 (resolve-dots 1 '(20 30) ... 4 '(40 50 60) .... 7)584 ; -> '(1 20 30 4 40 50 60 7)585 466 </enscript> 586 467 587 468 == Last update 588 469 589 Aug 01, 2020470 Nov 27, 2020 590 471 591 472 == Author … … 625 506 626 507 == Version History 508 ; 5.0 ; new version based again on Graham's dbind, using simple-sequences 627 509 ; 4.1 ; dotted lists in bodies added via resolve-dots 628 510 ; 4.0 ; dotted patterns added
Note: See TracChangeset
for help on using the changeset viewer.