Changeset 32913 in project


Ignore:
Timestamp:
11/17/15 16:16:13 (5 years ago)
Author:
juergen
Message:

bindings 4.0 docu

File:
1 edited

Legend:

Unmodified
Added
Removed
  • wiki/eggref/4/bindings

    r32605 r32913  
    22[[toc:]]
    33
    4 == Low-level macros made easy with bindings
    5 
    6 This module contains some macros to make the use of low-level macros
    7 easier. It replaces the now obsolete modules er-macros and ir-macros as
    8 well as low-level-macros.
    9 
    10 Recall that low-level macros are implemented as transformer routines,
    11 which are three-parameter procedures enclosed in er-macro-transformer or
    12 ir-macro-transformer respectively
    13 
    14 <enscript highlight=scheme>
    15 (er-macro-transformer
    16   (lambda (form rename compare?) ...))
    17 (ir-macro-transformer
    18   (lambda (form inject compare?) ...))
    19 </enscript>
    20 
    21 The programmer's job is to destructure the macro-code, form, and
    22 to either do the renaming of all symbols which should appear in
    23 the macro-expansion by hand in case of explicit-renaming, or to
    24 inject the symbols which should not be renamed in case of
    25 implicit-renaming. In both cases, symbols which are not renamed
    26 are unhygienic. The third parameter allows handling of additional
    27 keywords.
    28 
    29 Each of these transformer arguments does a special job, each of which is
    30 tedious and error-prone. In this module, we'll automate each of these
    31 jobs.
    32 
    33 Let's start with destructuring the macro-code. It can be done by a local
    34 macro, dbind, which follows Graham's classic "On Lisp", p. 232, very
    35 closely. Here is a Chicken version for lists:
     4== Procedural macros made easy with bindings
     5
     6The Scheme standard, R5RS, only provides declarative macros based on
     7syntax-rules. They are easy to use, but rather limited. For example, you
     8can only create hygienic macros, you have no control over the expansion
     9process, in particular, you can't use local procedures to be evaluated at
     10compile time. To overcome this limitations, R6RS offers syntax-case
     11macros, but that's a mouthfull ...
     12
     13Fortunately, Chicken offers two versions of procedural macros, explicit
     14and implicit renaming macros. They offer full flexibility without any
     15limitations but are tedious to use.
     16
     17First, you must care to avoid variable capture with renaming, if you
     18want hygienic macros, or you must decide which variables should be
     19captured on purpose. Implicit renaming here helps a lot: You simply
     20inject names which you want to be captured, the others are renamed
     21automatically by the runtime system.
     22
     23Second, you must do the destructuring of the macro code by hand.
     24Wouldn't it be nice, if this could be done automatically behind the
     25scene as well?
     26
     27This library provides the means for this to happen, in particular, two
     28binding routines, bind and bind-case. The former is a Scheme
     29implementation of Common Lisp's destructuring-bind, the latter a
     30case variant of the former, similar to the match macro of the matchable
     31library.
     32
     33Based on those binding routines and implicit renaming, some
     34macro-writing macros are defined, in paraticular, a hygienic procedural
     35define-macro and a procedural version of syntax-rules, named
     36macro-rules. The latter is almost as easy to use as syntax-rules, but
     37much more powerfull. Here is its syntax
     38
     39<macro>(macro-rules sym ... (keyword ...) (pat (where fender ...) .. tpl) ....)</macro>
     40
     41Note the special use of dots here and below: Three dots are ellipses, as
     42usual, i.e. the pattern on the left is repeated zero or more times, two
     43dots, zero or one time, 4 dots one ore several times.
     44
     45This form can be used instead of syntax-rules in define-syntax,
     46let-sytax and letrec-syntax, provided, you import it for-syntax.
     47sym ... denote the injected symbols to break hygiene (if there is none,
     48the constructed macro is hygienic). keyword ... and pat .... symbols are
     49as in syntax-rules, fender ... are expressions on pattern variables
     50which must pass for the pattern to match, and tpl .... are usually
     51quasiquoted expressions.
     52
     53And here is the syntax of define-macro
     54
     55<macro>(define-macro (name . args) (where fender ...) .. xpr ....))</macro>
     56
     57Note, that only this hygienic form survived in this version 4.0 of
     58the bindings library. To handle injected symbols or keywords use
     59macro-rules. And note also, that you need to import-for-syntax bind in
     60compiled code.
     61
     62The bind macro is patterned after Paul Graham's dbind, cf. his classic
     63"On Lisp", p. 232.  Here is a Chicken version for lists:
    3664
    3765<enscript highlight=scheme>
     
    5482                                  (loop p g 0))
    5583                            recu))))
    56                 (let ((tail `(list-tail ,seq ,n)))
    57                   (if (null? pat)
    58                     '()
    59                     `((,pat ,tail))))))))
     84                (if (null? pat)
     85                  '()
     86                  `((,pat (list-tail ,seq ,n))))))))
    6087        (dbind-ex
    6188          (lambda (binds body)
     
    77104</enscript>
    78105
    79 Its local procedures will be put in a helper library, macro-helpers,
    80 which must be available at compile-time. The code above will only work
    81 for lists. It does not check the length of the sequence expression and
    82 can not cope with non-symbol literals. Moreover, we want the underscore
    83 to be a wild-card, a symbol which matches everything but binds nothing.
    84 All this is done by additional procedures in the helper module, which
    85 are not documented here, contrary to many other procedures, which might
    86 be useful not only in macro writing.
     106This code works as follows: First, destruc traverses the pattern and
     107groups each symbol with some list accessing code, using gensyms to step
     108down the pattern while grouping the gensym bound object with all pairs
     109depending on this gensym. So, for example,
     110
     111<enscript highlight=scheme>
     112  (destruc '(a (b . c) . d) 'seq)
     113</enscript>
     114
     115will result in
     116
     117<enscript highlight=scheme>
     118  ((a (list-ref seq 0))
     119   ((#:g (list-ref seq 1)) (b (list-ref #:g 0)) (c (list-tail #:g 1)))
     120   (d (list-tail seq 2)))
     121</enscript>
     122
     123This tree is then transformed via dbind-ex into a nested let
     124
     125<enscript highlight=scheme>
     126  (let ((a (list-ref seq 0))
     127        (#:g (list-ref seq 1))
     128        (d (list-tail seq 2)))
     129    (let ((b (list-ref #:g 0))
     130          (c (list-tail #:g 1)))
     131      body))
     132</enscript>
     133 
     134Note, that the destructuring procedures are local to this macro. This is
     135necessary in Chicken for the macro to work, in particular in compiled
     136code, unless you import them for-syntax. But since they are of no
     137interest outside of the macro, local procedures are preferable.
     138
     139Note further, that ir-macro-transformer does all the necessary renaming
     140transparently behind the scene, even if the helpers where defined in
     141another module. In particular, gseq needn't be a gensym.
     142
     143And note, that Graham's code didn't check for seq's length, i.e.
     144(dbind (a b) '(1 2 3) (list a b) would happily return '(1 2).
     145
     146Graham's original code works on the sequence datatype, so vectors and
     147strings are destructured as well. Sequences don't exist in Scheme,
     148unless you import-for-syntax Felix' sequences egg. To make this module
     149self-contained, I prefer to supply access-routines closed over a table,
     150which provides sequence versions of list-ref and list-tail, the only
     151sequence routines used by destruc above, as well as a sequence version
     152of length, which is needed to do the length checks.
     153
     154There are some features, which I would like to have and which are
     155implemented as well. First wildcards, represented by the underscore
     156symbol. It matches everything, but binds nothing. So it can appear
     157multiple times in the same macro. Wildcard symbols are simply not
     158collected in the destruc routine.
     159
     160Second, non-symbol literals, which don't bind anything, of course, but
     161match only themselves. This and the length checks are treated simply by
     162pairing them as well with check-routines in destruc but separating the
     163pairs with leading symbol from those with leading nil or literal in
     164dbind-ex. The former are bound with lets as in Graham's code, the
     165latter's cadrs being evaluated before the recursive call to dbind-ex.
     166
     167The last feature missing is fenders, which is important in particular
     168for bind-case and can easily be implemented with a where clause: A
     169pattern matches successfully if only each pattern variable can be bound
     170and the where clause is satisfied. If the where clause doesn't pass, the
     171next pattern is tried in bind-case or a bind-exception is signalled in
     172bind.
    87173
    88174== Bindings
     
    90176Off course, automatic destructuring of expressions is not only of
    91177interest in macro writing. For example, the ML-family of programming
    92 languages is based on it. Therefore, this module provides a bunch of
    93 macros, all starting with the bind prefix, and all being derived from the
    94 internal macro dbind and related procedures. They all destructure
    95 arbitrary mixtures of (pseudo-) lists, vectors and strings, which match
    96 a pattern, and can be easily enhanced, to accept other sequence types as
    97 well, tuples and arrays, for example. Here, a pattern is a nested
    98 pseudolist of symbols.
    99 
    100 == Documentation
    101 
    102 This documentation uses special ellipses, .. or ...., to repeat the
    103 pattern to the left at most once or at least once respectively
    104 
    105 == Programming interface
    106 
    107 === The module macro-helpers
    108 
    109 ==== macro-helpers
    110 
    111 <procedure>(macro-helpers sym ..)</procedure>
    112 
    113 shows which symbols are not only exported, but of general interest, if
    114 called with no argument, or sym's documentation.
    115 
    116 ==== symbol-dispatcher
    117 
    118 <procedure>(symbol-dispatcher alist)</procedure>
    119 
    120 creates a documentation procedure as used by macro-helpers and
    121 low-level-macros.
     178languages is based on it. Therefore, this library provides a bunch of
     179macros, all starting with the bind prefix, and all being derived from
     180bind and related procedures. They all destructure arbitrary mixtures of
     181(pseudo-) lists, vectors and strings, which match a pattern, and can be
     182easily enhanced, to accept other sequence types as well, arrays, for
     183example. Here, a pattern is a nested pseudolist of symbols.
     184
     185=== The module basic-bindings
     186
     187==== basic-bindings
     188
     189<procedure>(basic-bindings sym ..)</procedure>
     190
     191documentation procedure. Shows the exported symbols and the syntax of
     192such an exported symbol, respectively.
     193
     194====  bind
     195
     196<macro>(bind pat seq (where fender ...) .. xpr ....)</macro>
     197
     198binds pattern variables of pat to subexpressions of seq and executes
     199xpr .... in this context, provided all fenders return #t, if supplied.
     200
     201==== bindable?
     202
     203<macro>(bindable? pat (where fender ...))</macro>
     204
     205returns a unary predicate which checks, if its sequence argument matches
     206the pattern argument, pat, of bindable? and passes all of its fenders
     207(the syntax is slightly changed for consistency).
     208
     209====  bind-case
     210
     211<macro>(bind-case seq (pat (where fender ...) .. xpr ....) ....)</macro>
     212
     213Matches seq against a series of patterns and executes the body of the
     214first matching pattern satisfying fenders (if given).
     215
     216==== bind-define
     217
     218<macro>(bind-define pat seq)</macro>
     219
     220defines pattern variables of pat with values matching subexpressions of seq in one go
     221
     222==== bind-set!
     223
     224<macro>(bind-set! pat seq)</macro>
     225
     226sets symbols of pat to corresponding subexpressions of seq
    122227
    123228==== bind-exception
     
    127232generates a composite condition of type (exn bind) with location loc,
    128233message msg and arguments args.
    129 Imported and reexported by bindings
    130 
    131 ==== add-prefix
    132 
    133 <procedure>(add-prefix pref id)</procedure>
    134 
    135 adds a prefix to a symbol.
    136 
    137 ==== prefixed-with?
    138 
    139 <procedure>(prefixed-with? pre)</procedure>
    140 
    141 returns a predicate, which checks, if pre is a prefix of its argument.
    142 
    143 ==== strip-prefix
    144 
    145 <procedure>(strip-prefix pre id)</procedure>
    146 
    147 strips the prefix pre from the identifier id.
    148 
    149 ==== strip-suffix
    150 
    151 <procedure>(strip-suffix suf id)</procedure>
    152 
    153 strips the suffix suf from the identifier id.
    154 
    155 ==== extract
    156 
    157 <procedure>(extract ok? tree)</procedure>
    158 
    159 returns a flat list of all the symbols in a tree which pass the ok?
    160 test.
    161 
    162 ==== remove-duplicates
    163 
    164 <procedure>(remove-duplicates lst)</procedure>
    165 
    166 returns a sublist of lst with dups removed.
    167 
    168 ==== adjoin
    169 
    170 <procedure>(adjoin obj lst)</procedure>
    171 
    172 conses obj to lst provided it isn't already there.
    173 
    174 ==== memp
    175 
    176 <procedure>(memp ok? lst)</procedure>
    177 
    178 returns the tail of lst, whose car passes ok?, or #f otherwise.
    179 
    180 ==== assp
    181 
    182 <procedure>(assp ok? tbl)</procedure>
    183 
    184 returns the table item whose car passes ok?
    185 
    186 ==== replace*
    187 
    188 <procedure>(replace* what? by tree)</procedure>
    189 
    190 substitutes each old with (what? old) by (by old) in a tree.
    191 
    192 ==== map*
    193 
    194 <procedure>(map* fn . trees)</procedure>
    195 
    196 tree-version of map. Returns a tree.
    197 
    198 ==== flatten
    199 
    200 <procedure>(flatten tree)</procedure>
    201 
    202 returns a flat list with all the items of tree.
    203 
    204 ==== flatten-map*
    205 
    206 <procedure>(flatten-map* fn . trees)</procedure>
    207 
    208 combination of flatten and map*. Returns a list.
    209 
    210 ==== filter
    211 
    212 <procedure>(filter ok? lst)</procedure>
    213 
    214 returns two sublists of lst where each item passes ok? or not ok?
    215 respectively.
    216 
    217 ==== filter*
    218 
    219 <procedure>(filter* ok? tree)</procedure>
    220 
    221 returns two subtrees of tree where each item passes ok? or not ok?
    222 respectively.
    223 
    224 ==== collect*
    225 
    226 <procedure>(collect* ok? tree)</procedure>
    227 
    228 where ok? operates on trees. Returns a list of trees which passed ok?
    229 
    230 ==== found?
    231 
    232 <procedure>(found? ok? tree)</procedure>
    233 
    234 predicate which checks if tree contains an item which passed ok?
    235 
    236 ==== mappend
    237 
    238 <procedure> (mappend fn lists)</procedure>
    239 
    240 combination of map and append, i.e. mapcan in CL.
    241 
    242 ==== plist?
    243 
    244 <procedure>(plist? xpr)</procedure>
    245 
    246 is xpr a pseudolist? Allways #t.
    247 
    248 ==== pnull?
    249 
    250 <procedure>(pnull? xpr)</procedure>
    251 
    252 is xpr a null? pseudolist? For example (pnull? 1) is true.
    253 
    254 ==== plength
    255 
    256 <procedure>(plength pl)</procedure>
    257 
    258 returns the length of a pseudolist. For example (plength 1) is 0.
    259 Imported for-syntax and reexported by low-level-macros.
    260 
    261 ==== plist-ref
    262 
    263 <procedure>(plist-ref pl k)</procedure>
    264 
    265 returns the kth item of a pseudolist.
    266 Imported for-syntax and reexported by low-level-macros.
    267 
    268 ==== plist-tail
    269 
    270 <procedure>(plist-tail pl k)</procedure>
    271 
    272 returns two values, the tail, starting from k, and the head upto k,
    273 of a pseudolist.
    274 Imported for-syntax and reexported by low-level-macros.
    275 
    276 ==== plist-head
    277 
    278 <procedure>(plist-head pl k)</procedure>
    279 
    280 the head part of plist-tail.
    281 
    282 ==== ptail
    283 
    284 <procedure>(ptail pl)</procedure>
    285 
    286 returns the atom part of the pseudolist pl.
    287 
    288 ==== phead
    289 
    290 <procedure>(phead pl)</procedure>
    291 
    292 returns the list part of the pseudolist pl.
    293 
    294 ==== seq-length
    295 
    296 <procedure>(seq-length seq)</procedure>
    297 
    298 returns the length of the generic sequence seq,
    299 presently a string, vector or (pseudo-)list.
    300 
    301 ==== seq-ref
    302 
    303 <procedure>(seq-ref seq n)</procedure>
    304 
    305 returns the nth item of the generic sequence seq,
    306 presently a string, vector or (pseudo-)list.
    307 
    308 ==== seq-tail
    309 
    310 <procedure>(seq-tail seq n)</procedure>
    311 
    312 returns the tail of the generic sequence seq,
    313 presently a string, vector or (pseudo-)list, starting at n.
    314 
    315 ==== vector-tail
    316 
    317 <procedure>(vector-tail vec k)</procedure>
    318 
    319 returns two values the subvector of vec starting with index k, and the
    320 subvector upto k.
    321 
    322 ==== vector-head
    323 
    324 <procedure>(vector-head vec k)</procedure>
    325 
    326 returns the head value of vector-tail.
     234
     235==== bind-exception-handler
     236
     237<procedure>(bind-exception-handler var)</procedure>
     238
     239exception-handler to be passed to the parameter
     240current-exception-handler
     241
     242==== signal-bind-exception
     243
     244<procedure>(signal-bind-exception loc msg arg ...)</procedure>
     245
     246signals a bind-exception, can be used instead of error.
     247
     248==== bind-table-show
     249
     250<procedure>(bind-table-show)</procedure>
     251
     252prints the contents of the table
     253
     254==== bind-table-add!
     255
     256<procedure>(bind-table-add! type? len ref tail)</procedure>
     257
     258adds a custom new list of sequence operators to the top of the table
     259(in previous versions of the library named seq-length-ref-tail!)
     260
     261==== bind-seq-length
     262
     263<procedure>(bind-seq-length seq)</procedure>
     264
     265returns the length of the generic sequence seq
     266(previously named seq-length)
     267
     268==== bind-seq-ref
     269
     270<procedure>(bind-seq-ref seq n)</procedure>
     271
     272returns the nth item of the generic sequence seq
     273(preveiously named seq-ref)
     274
     275==== bind-seq-tail
     276
     277<procedure>(bind-seq-tail seq n)</procedure>
     278
     279returns the tail of the generic sequence seq, starting at n
     280(previously named seq-tail)
     281
     282==== symbol-dispatcher
     283
     284<procedure>(symbol-dispatcher alist)</procedure>
     285
     286creates a documentation procedure as used in all modules
     287of this library.
    327288
    328289==== list-of
     
    331292
    332293returns a predicate which checks, if its list argument passes every
    333 predicate of the oks? list.
    334 Imported and reexported by bindings.
    335 
    336 ==== atom?
    337 
    338 <procedure>(atom? xpr)</procedure>
    339 
    340 same as (not (pair? xpr)).
    341 
    342 ==== singleton?
    343 
    344 <procedure>(singleton? xpr)</procedure>
    345 
    346 evaluates xpr to a list of length one?
    347 
    348 ==== rename-prefix
    349 
    350 <parameter>(rename-prefix pre ..)</parameter>
    351 
    352 defines or changes the prefix which is used in the three er-macros of
    353 the bindings module. Default is %.
    354 
    355 === The module bindings
    356 
    357 The bindings module is a light-weight alternative to the matchable egg
    358 together with some enhancements, in particular the bind macro, which is
    359 Common Lisp's destructuring-bind.
    360 
    361 Contrary to matchable, there is no attempt to implement ellipses,
    362 Scheme's dotted lists must do. Instead of the match macro you should use
    363 bind-case. And contrary to matchable, all binding macros can destructure
    364 arbitrary nested sequences, i.e. mixtures of lists, pseudo-lists,
    365 vectors and strings. Other types of sequences can be added by clients.
    366 
    367 ==== bindings
    368 
    369 <procedure>(bindings sym ..)</procedure>
    370 
    371 Documentation procedure.
    372 Called without argument it returns the list of exported symbols, with
    373 one of those symbols as argument it returns its documentation.
    374 
    375 ====  bind
    376 
    377 <macro>(bind pat seq (where . fenders) .. xpr ....)</macro>
    378 
    379 binds pattern variables of pat to subexpressions of seq and executes xpr
    380 . xprs in this context, provided all fenders return #t, if supplied.
    381 
    382 ==== bindable?
    383 
    384 <macro>(bindable? pat . fenders)</macro>
    385 
    386 returns a unary predicate which checks, if its sequence argument matches
    387 the pattern argument, pat, of bindable? and passes all of its fenders.
    388 
    389 ====  bind-case
    390 
    391 <macro>(bind-case seq (pat (where . fenders) .. xpr ....) ....)</macro>
    392 
    393 Matches seq against a series of patterns and executes the body of the
    394 first matching pattern satisfying fenders (if given).
    395 
    396 ==== bind-case-lambda
    397 
    398 <macro>(bind-case-lambda (pat (where . fenders) .. xpr ....) ....)</macro>
    399 
    400 Combination of bind-case and lambda with one pattern argument
    401 
    402 ==== bind-case-lambda*
    403 
    404 <macro>(bind-case-lambda* (pat (where . fenders) .. xpr ....) ....)</macro>
    405 
    406 Combination of bind-case and lambda with multiple pattern arguments
    407 
    408 ==== bind-lambda
    409 
    410 <macro>(bind-lambda pat (where . fenders) .. xpr ....)</macro>
    411 
    412 combination of lambda and bind, one pattern argument
    413 
    414 ====  bind-lambda*
    415 
    416 <macro>(bind-lambda* pat (where . fenders) .. xpr ....)</macro>
    417 
    418 combination of lambda and bind, multiple pattern arguments
    419 
    420 ====  bind-let
    421 
    422 <macro>(bind-let loop .. ((pat seq) ...) xpr ....)</macro>
    423 
    424 like let, named and unnamed, but binds patterns to sequence templates.  In the named case loop is bound to a one-parameter-procedure accessible in the body xpr ....
    425 
    426 ==== bind-let*
    427 
    428 <macro>(bind-let* ((pat seq) ...) xpr ....)</macro>
    429 
    430 like let*, but binds patterns to sequence templates
    431 
    432 ==== bind-letrec
    433 
    434 <macro>(bind-letrec ((pat seq) ...) xpr ....)</macro>
    435 
    436 like letrec, but binds patterns to sequence templates
    437 
    438 ==== bind*
    439 
    440 <macro>(bind* loop pat seq xpr ....)</macro>
    441 
    442 named version of bind.
    443 loop is bound to a one-parameter procedure, which can be used in the body xpr ....
    444 
    445 ==== bindrec
    446 
    447 <macro>(bindrec pat seq xpr ....)</macro>
    448 
    449 bind pattern variables of pat to subsequences of seq recursively
    450 
    451 ==== bind-define
    452 
    453 <macro>(bind-define pat seq)</macro>
    454 
    455 defines pattern variables of pat with values matching subexpressions of seq in one go
    456 
    457 ==== bind-set!
    458 
    459 <macro>(bind-set! pat seq)</macro>
    460 
    461 sets symbols of pat to corresponding subexpressions of seq
    462 
    463 As implemented, the binding macros can handle arbitrary nested
    464 combinations of (pseudo-)lists, vectors and strings. But updating the
    465 table additional sequence types can be handled without touching the
    466 macros' code.
    467 
    468 ==== bind/cc
    469 
    470 <macro>(bind/cc cc xpr ....)</macro>
    471 
    472 captures the current continuation in cc and executes xpr .... in this
    473 context.
    474 
    475 === low-level macro generators
    476 
    477 ==== once formal parameters
    478 
    479 All remaining macros will accept once formal parameters, i.e.
    480 expressions of the form (once arg). This will inform the macro
    481 generators, that the symbol arg should only be evaluated once.
    482 For example
    483 
    484 <enscript highlight=scheme>
    485 (define-macro (square (once x)) `(* ,x ,x))
    486 </enscript>
    487 
    488 works like a procedure, even if x is supplied the value of a procedure
    489 with side-effects.
     294predicate ok? ...
     295
     296==== vector-of
     297
     298<procedure>(vector-of ok? ...)</procedure>
     299
     300returns a predicate which checks, if its vector argument passes every
     301predicate ok? ...
     302
     303
     304=== The module macro-bindings
     305
     306==== macro-bindings
     307
     308<procedure>(macro-bindings sym ..)</procedure>
     309
     310documentation procedure. Shows the exported symbols and the syntax of
     311such an exported symbol, respectively.
    490312
    491313==== macro-rules
    492314
    493 <macro>(macro-rules sym ... (keyword ...) (pat (where . fenders) .. tpl) ....)</macro>
     315<macro>(macro-rules sym ... (keyword ...) (pat (where fender ...) .. tpl) ....)</macro>
    494316
    495317like syntax-rules, but the templates are usually quasiquote-expressions.
     
    505327==== define-macro
    506328
    507 <macro>(define-macro name macro-rules-expression)</macro>
    508 <macro>(define-macro (name . args) xpr ....))</macro>
    509 <macro>(define-macro (name . args) (inject sym ...) xpr ....))</macro>
    510 <macro>(define-macro (name . args) (inject sym ...) (keywords key ...) xpr ....))</macro>
    511 <macro>(define-macro (name . args) (keywords key ...) (inject sym ...) xpr ....))</macro>
    512 
    513 generates an implicit-renaming macro, name. Keywords and injected
    514 symbols are extracted from the macro body and transformed into
    515 appropriate subexpressions of the macro-transformer. Probably only the
    516 first two versions will be used.
    517 
    518 ==== let-macro
    519 
    520 <macro>(let-macro ((name macro-rules-expression) ....) xpr .  xprs)</macro>
    521 
    522 an alternative to let-syntax using macro-rules expressions instead of
    523 syntax-rules expressions.
    524 
    525 ==== letrec-macro
    526 
    527 <macro>(letrec-macro ((name macro-rules-expression) ....) xpr .  xprs)</macro>
    528 
    529 an alternative to letrec-syntax using macro-rules expressions instead of
    530 syntax-rules expressions.
    531 
    532 
    533 ==== define-er-macro
    534 
    535 <macro>(define-er-macro (name . args) (keywords key ...) .. xpr ....)</macro>
    536 
    537 
    538 Defines an explicit-renaming macro by renaming every symbol in the body
    539 which starts with the prefix defined in the parameter rename-prefix,
    540 which defaults to %.
    541 
    542 ==== let-er-macro
    543 
    544 <macro>(let-er-macro ((code . body) ....) xpr ....)</macro>
    545 
    546 where (code . body) ....  are as in define-er-macro.
    547 
    548 This is a local version of define-er-macro, allowing a list of (code . body)
    549 lists to be processed in xpr .... in parallel.
    550 
    551 ==== letrec-er-macro
    552 
    553 <macro>(letre-er-macro ((code . body) ....) xpr ....)</macro>
    554 
    555 where (code . body) ....  are as in define-er-macro.
    556 
    557 This is a local version of define-er-macro, allowing a list of (code . body)
    558 lists to be processed in xpr .... recursively.
     329<macro>(define-macro (name . args) (where fender ...) .. xpr ....))</macro>
     330
     331generates a hygienic implicit-renaming macro, name.
     332
     333==== macro-let
     334
     335<macro>(macro-let (((name . args) (where fender ...) .. xpr ...) ...) body ....)</macro>
     336
     337evaluates body ... in the context of parallel hygienic macros name ....
     338
     339==== macro-letrec
     340
     341<macro>(macro-letrec (((name . args) (where fender ...) .. xpr ...) ...) body ....)</macro>
     342
     343evaluates body ... in the context of recursive hygienic macros name ....
    559344
    560345==== once-only
    561346
    562 <macro>(once-only (x ...) . body)</macro>
     347<macro>(once-only (x ...)  body ....)</macro>
    563348
    564349to be used in a macro-body to avoid side-effects.
     
    573358with-gensyms must be imported for-syntax.
    574359
    575 ==== define-syntax-rule
    576 
    577 <macro>(define-syntax-rule (name . args) (keywords x ...) .. tpl)</macro>
    578 
    579 the only high-level macro. To be used instead of syntax-rules in case
    580 there is only one rule and no additional keywords.
    581 
    582 ==== seq-length-ref-tail!
    583 
    584 <procedure>(seq-length-ref-tail! type? type-length type-ref type-tail)</procedure>
    585 
    586 adds custom sequence types for use with bind and friends.
    587 
    588 ==== bind-exception
    589 
    590 <procedure>(bind-exception loc msg . args)</procedure>
    591 
    592 generates a composite condition of type (exn bind) with location loc,
    593 message msg and arguments args.
    594 
    595 <procedure>(list-of ok? ...)</procedure>
    596 
    597 returns a predicate which checks, if its list argument passes every
    598 predicate of the oks? list.
     360=== The module more-bindings
     361
     362==== more-bindings
     363
     364<procedure>(more-bindings sym ..)</procedure>
     365
     366documentation procedure. Shows the exported symbols and the syntax of
     367such an exported symbol, respectively.
     368
     369==== bind-lambda
     370
     371<macro>(bind-lambda pat (where fender ...) .. xpr ....)</macro>
     372
     373combination of lambda and bind, one pattern argument
     374
     375====  bind-lambda*
     376
     377<macro>(bind-lambda* pat (where fender ...) .. xpr ....)</macro>
     378
     379combination of lambda and bind, multiple pattern arguments
     380
     381==== bind*
     382
     383<macro>(bind* loop pat seq xpr ....)</macro>
     384
     385named version of bind.
     386loop is bound to a one-parameter procedure, which can be used in the body xpr ....
     387
     388==== bindrec
     389
     390<macro>(bindrec pat seq xpr ....)</macro>
     391
     392bind pattern variables of pat to subsequences of seq recursively
     393
     394====  bind-let
     395
     396<macro>(bind-let loop .. ((pat seq) ...) xpr ....)</macro>
     397
     398like let, named and unnamed, but binds patterns to sequence templates.  In the named case loop is bound to a one-parameter-procedure accessible in the body xpr ....
     399
     400==== bind-let*
     401
     402<macro>(bind-let* ((pat seq) ...) xpr ....)</macro>
     403
     404like let*, but binds patterns to sequence templates
     405
     406==== bind-letrec
     407
     408<macro>(bind-letrec ((pat seq) ...) xpr ....)</macro>
     409
     410like letrec, but binds patterns to sequence templates
     411
     412==== bind-case-lambda
     413
     414<macro>(bind-case-lambda (pat (where fender ...) .. xpr ....) ....)</macro>
     415
     416Combination of bind-case and lambda with one pattern argument
     417
     418==== bind-case-lambda*
     419
     420<macro>(bind-case-lambda* (pat (where fender ...) .. xpr ....) ....)</macro>
     421
     422Combination of bind-case and lambda with multiple pattern arguments
     423
     424==== bind/cc
     425
     426<macro>(bind/cc cc xpr ....)</macro>
     427
     428captures the current continuation in cc and executes xpr .... in this
     429context.
     430
     431=== The module bindings
     432
     433This convenience module imports and reexports all the routines of the modules above.
     434
     435==== bindings
     436
     437<procedure>(bindings sym ..)</procedure>
     438
     439documentation procedure. Shows the exported symbols and the syntax of
     440such an exported symbol, respectively.
    599441
    600442=== Requirements
     
    605447
    606448<enscript highlight=scheme>
    607 (import bindings)
    608 (import-for-syntax (only macro-helpers with-gensyms once-only))
     449(use bindings)
     450(import-for-syntax (only bindings bind macro-rules with-gensyms once-only))
    609451</enscript>
    610452
     
    613455<enscript highlight=scheme>
    614456
    615 (use bindings tuples)
    616 (import-for-syntax (only bindings macro-rules)
    617                    (only macro-helpers with-gensyms once-only))
     457(use bindings)
     458(import-for-syntax
     459  (only bindings bind macro-rules with-gensyms once-only list-of bindable?))
    618460
    619461(let ((stack #f) (push! #f) (pop! #f))
     
    642484; -> 0
    643485
    644 (bind a 1 a) ; -> 1
    645 
    646 (bind (x y z w) '(1 2 3 4) (list x y z w) ; -> '(1 2 3 4)
    647 
    648 (bind (x . y) '#(1 2 3 4) (list x y)) ; -> '(1 #(2 3 4))
     486(bind a 1 a)
     487; -> 1
     488
     489(bind (x y z w) '(1 2 3 4) (list x y z w))
     490; -> '(1 2 3 4)
     491
     492(bind (x . y) '#(1 2 3 4) (list x y))
     493; -> '(1 #(2 3 4))
    649494
    650495(bind (x (y (z u . v)) w) '(1 #(2 "foo") 4)
     
    727572; -> '(#t #f)
    728573
    729 (let ((two '(1 2)))
    730   (bind-matches? two ()))
     574((bindable? ()) '())
     575; -> #t
     576
     577((bindable? (a (b C) . d)) '(1 (2 3) . 4))
     578; -> #t
     579
     580((bindable? (a (b C) . d)) '(1 #(2 3) 4 5))
     581; -> #t
     582
     583((bindable? (a (b . C) . d)) '(1 (2 3) 4))
     584; -> #t
     585
     586((bindable? (a (b . C) . d)) '#(1 2 3 4 5))
    731587; -> #f
    732588
    733 ((bindable? ()) '()) ; -> #t
    734 
    735 ((bindable? (a (b C) . d)) '(1 (2 3) . 4)) ; -> #t
    736 
    737 ((bindable? (a (b C) . d)) '(1 #(2 3) 4 5)) ; -> #t
    738 
    739 ((bindable? (a (b . C) . d)) '(1 (2 3) 4)) ; -> #t
    740 
    741 ((bindable? (a (b . C) . d)) '#(1 2 3 4 5)) ; -> #f
    742 
    743 ((bindable? (a (b C) d)) '(1 (2 3) 4 5)) ; -> #f
    744 
    745 ((bindable? (a b) (even? a)) '#(1 2)) ; -> #f
     589((bindable? (a (b C) d)) '(1 (2 3) 4 5))
     590; -> #f
     591
     592((bindable? (a b) (even? a)) '#(1 2))
     593; -> #f
    746594
    747595(bind-case '#(1 2)
     
    793641; -> '(1 20 #(30 40) (2 3) 4 (5 6))
    794642
    795 ;;adding new types to generics
    796 (seq-length-ref-tail!  tuple?  tuple-length tuple-ref tuple-from-upto)
    797 (bind (x y z) (tuple 1 2 3) (list x y z)) ;-> '(1 2 3)
    798 (bind (x (y z)) (vector 0 (tuple 1 2)) (list x y z)) ;-> '(0 1 2)
     643;;adding arrays to generic sequence table
     644(bind-table-add!  array?
     645                  array-length
     646                  (lambda (seq k)
     647                    (array-item k seq))
     648                  (lambda (seq k)
     649                    (array-drop k seq)))
     650
     651(bind (x y z) (array 1 2 3) (list x y z))
     652;-> '(1 2 3)
     653
     654(bind (x (y z)) (vector 0 (array 1 2)) (list x y z))
     655;-> '(0 1 2)
     656
     657(bind (x (y . z)) (vector 0 (array 1 2 3 4)) (list x y z))
     658;-> '(0 1 @(2 3 4))
    799659
    800660;; two anaphoric macros
    801 (define-macro aif
     661(define-syntax aif
    802662  (macro-rules it ()
    803663    ((_ test consequent)
     
    820680                  choices)))))
    821681
    822 ;; two versions of a verbose if
    823 (define-er-macro (verbose-if test (then . xprs) (else . yprs))
    824   (keywords then else)
    825   `(,%if ,test
    826      (,%begin ,@xprs)
    827      (,%begin ,@yprs)))
    828 
    829 (define-macro vif
     682(define-syntax vif
    830683  (macro-rules (then else)
    831684    ((_ test (then xpr . xprs))
     
    840693        (begin ,ypr ,@yprs)))))
    841694
    842 ;; low-level version of cond
    843 (define-macro my-cond
     695;; procedural version of cond
     696(define-syntax my-cond
    844697  (macro-rules (else =>)
    845698    ((_ (else xpr . xprs))
     
    866719        (my-cond ,@clauses)))))
    867720
    868 ;; low-level version of letrec
    869 (define-macro (my-letrec pairs . body)
    870   (let ((vars (map car pairs))
    871         (vals (map cadr pairs))
    872         (aux (map (lambda (x) (gensym)) pairs)))
     721;; procedural version of letrec
     722(define-macro (my-letrec var-val-pairs . body)
     723              (where ((list-of (bindable? (var val)))
     724                      var-val-pairs))
     725  (let ((vars (map car var-val-pairs))
     726        (vals (map cadr var-val-pairs))
     727        (aux (map (lambda (x) (gensym)) var-val-pairs)))
    873728    `(let ,(map (lambda (var) `(,var #f)) vars)
    874729       (let ,(map (lambda (a v) `(,a ,v)) aux vals)
     
    876731         ,@body))))
    877732
     733(my-letrec ((o? (lambda (m) (if (zero? m) #f (e? (- m 1)))))
     734            (e? (lambda (n) (if (zero? n) #t (o? (- n 1))))))
     735           (list (o? 95) (e? 95)))
     736
     737;; local macros
     738(letrec-syntax (
     739     (sec (macro-rules ()
     740               ((_ lst) `(car (res ,lst)))))
     741     (res (macro-rules ()
     742             ((_ lst) `(cdr ,lst))))
     743     )
     744     (sec '(1 2 3)))
     745;-> 2
     746
     747(macro-letrec (
     748     ((sec lst) `(car (res ,lst)))
     749     ((res lst) `(cdr ,lst))
     750     )
     751     (sec '(1 2 3)))
     752;-> 2
     753
     754(macro-let (
     755     ((fir lst) (where (list? lst)) `(car ,lst))
     756     ((res lst) (where (list? lst)) `(cdr ,lst))
     757     )
     758     (fir (res '(1 2 3))))
     759;-> 2
     760
    878761;; non-symbolic literals
    879 (define-macro foo
     762(define-syntax foo
    880763  (macro-rules ()
    881764    ((_ "foo" x) x)
     
    885768    ((_ a b) (where (odd? a)) `(list ,a ,b))
    886769    ((_ a b) a)))
    887 (foo "foo" 1) ; -> 1
    888 (foo "bar" 2) ; -> '("bar" 2)
    889 (foo #f 'blabla) ; -> '(false)
    890 (foo 1 2) ; -> '(1 2)
    891 (foo 2 3) ; -> 2
    892 
    893 ;; once formal paramteters
    894 (define-er-macro (osquare (once x)) `(,%* ,x ,x))
    895 (let ((x 5)) (osquare ((lambda () (set! x (* x 10)) x))))
    896    ; -> 2500
    897 (define-er-macro (square x) `(,%* ,x ,x))
    898 (let ((x 5)) (square ((lambda () (set! x (* x 10)) x))))
    899    ; -> 25000
    900 
    901 ;; odd? and even? as letrec-macro
    902 (letrec-macro ((odd? (macro-rules ()
    903                        ((_ n) `(if ,(zero? n) #f ,(even?
    904                                                         (- n 1))))))
    905                (even? (macro-rules ()
    906                         ((_ n) `(if ,(zero? n) #t ,(odd? (- n 1)))))))
    907               (even?  286))
     770(foo "foo" 1)
     771; -> 1
     772(foo "bar" 2)
     773; -> '("bar" 2)
     774(foo #f 'blabla)
     775; -> '(false)
     776(foo 1 2)
     777; -> '(1 2)
     778(foo 2 3)
     779; -> 2
     780
    908781</enscript>
    909782
    910783== Last update
    911784
    912 June 08, 2015
     785Nov 15, 2015
    913786
    914787== Author
     
    948821
    949822== Version History
     823; 4.0: code completely rewritten,simplified  and reorganized, some small syntax changes
    950824; 3.5.2: code reorganized again to fix compile problems
    951825; 3.5.1: code reorganized
Note: See TracChangeset for help on using the changeset viewer.