Changeset 38014 in project


Ignore:
Timestamp:
12/13/19 18:21:10 (10 months ago)
Author:
juergen
Message:

bindings 2.0 docu

File:
1 edited

Legend:

Unmodified
Added
Removed
  • wiki/eggref/5/bindings

    r37351 r38014  
    1212
    1313This library provides an alternative to matchable, a bunch of macros,
    14 all starting with the bind prefix, and all being derived from bind and
    15 related macros.  They all destructure arbitrary mixtures of
    16 (pseudo-) lists, vectors and strings, which match a pattern, and can be
    17 easily enhanced, to accept other sequence types as well, arrays, for
    18 example. For this to be possible, sequence equivalents for list-ref,
    19 list-tail and null? have to be implemented, which use a database routine
    20 named bind-seq-db.
    21 
    22 The syntax of the fundamental bind macro is as follows
    23 
    24 <macro>(bind pat seq (where fender ...) .. xpr ....)</macro>
     14all starting with the bind prefix, and all being derived from bind-set!
     15and related macros.  They destructure nested pseudolist which match a
     16pattern and can be easily enhanced to accept other sequence types as
     17well, vectors, strings, arrays, or what have you. All this sequence
     18types can be nested and mixed as you need it. This flexibility is made
     19possible by one generic function, bind-seq->list, which can add the
     20necessary transformers to its local database.
     21
     22The syntax of the fundamental bind-set! macro is as follows
     23
     24<macro>(bind-set! pat seq)</macro>
    2525
    2626Here, a pattern, pat, is a nested psudolist of (mostly) symbols, seq a
    2727sequencce expression, i.e. a mixture of pseudolists, vectors and
    28 strings, fender a check expression on pattern variables, var, of the form
    29 (var ok? ...) and xpr ....  constitute the body of the macro. Note the
    30 special use of dots here and below: Three dots repeat the expression to
    31 the left zero or many times, two dots zero or one times and four dots
    32 one or many times.
    33 
    34 This macro binds pattern variables, i.e. symbols of pat, to corresponding
    35 sequenceds of seq, checks, if the fenders succeed and exectutes the body
    36 in this context.
     28strings (after having added string and vector support).
     29
     30This macro sets pattern variables, i.e. symbols of pat, to corresponding
     31sequences of seq and does the necessary checks.
    3732
    3833There are some features, which I would like to have and which are
    3934implemented as well. First wildcards, represented by the underscore
    4035symbol. It matches everything, but binds nothing. So it can appear
    41 multiple times in the same macro. Wildcard symbols are simply not
    42 collected in the internal destructure routine.
     36multiple times in the same macro.
    4337
    4438Second, non-symbol literals, which don't bind anything, of course, but
    4539match only expressions evaluating to themselves.
    4640
    47 The last feature missing is fenders, which is important in particular
    48 for bind-case and can easily be implemented with a where clause: A
    49 pattern matches successfully if only each pattern variable can be bound
    50 and the checks as well as the fenders are satisfied. If the where
    51 clause doesn't pass, the next pattern is tried in bind-case or a
    52 bind-seq-exception is signalled in bind.
    53 
    54 This version is a port to chicken-5 from the last version 7.1 of
    55 chicken-4, which in turn was a complete rewrite. The code no longer
    56 uses Graham's dbind implementation. Instead, a direct implementation of
    57 bind is given, which doesn't need gensyms. The internal destructure
    58 routine transforms the pattern and sequence arguments into three lists,
    59 pairs, literals and tails. Pairs is a list of pattern-variable and
    60 corresponding sequence-accesscode pairs to be used in a let at runtime,
    61 literals and tails check for equality of literals and their
    62 corresponding sequence values, and the emptyness of sequence tails
    63 corresponding to null patterns respectively. So, contrary to Graham's
    64 dbind, an exception is raised if the lengths of a pattern and its
    65 corresponding sequence don't match. Fenders are supplied in a where
    66 clause at the very beginning of the macro body: A list of
    67 pattern-variable predicates pairs is internally transformed into a list
    68 of predicate calls.
    69 
    70 Algebraic types of the latest chicken-4 version are removed and will be
    71 outsourced to another egg.
     41In former versions of the bindings egg we had a where clause to test for
     42fenders. It's removed here because it can simply be added in the client
     43code: Use >> from the checks egg.
     44
     45Notice the meaning of dots following an expression in the sequel.
     46two dots: the expression appears zero or one times,
     47three dots: zero or many times,
     48four dots: one or many times.
    7249
    7350=== Documentation
     
    8057such an exported symbol, respectively.
    8158
    82 === Sequence routines
    83 
    84 ==== bind-pseudo-list?
    85 
    86 <procedure>(bind-pseudo-list? xpr)</procedure>
    87 
    88 always #t
    89 
    90 ==== bind-seq-exception
    91 
    92 <procedure>(bind-seq-exception loc . args)</procedure>
    93 
    94 generates an exception to be raised
    95 
    96 ==== bind-seq-db
    97 
    98 <procedure>(bind-seq-db)</procedure>
    99 
    100 shows the sequence database
    101 
    102 <procedure>(bind-seq-db type? ref: ref tail: tail)</procedure>
    103 
    104 adds a new custom sequence type with predicate type? and keyword
    105 arguments ref: and tail:  naming procedures to be later accessed
    106 via bind-seq-ref and bind-seq-tail respectively.
    107 
    108 ==== bind-seq-ref
    109 
    110 <procedure>(bind-seq-ref seq k)</procedure>
    111 
    112 sequence analog of list-ref
    113 
    114 ==== bind-seq-tail
    115 
    116 <procedure>(bind-seq-tail seq k)</procedure>
    117 
    118 sequence analog of list-tail
    119 
    120 ==== bind-seq-null?
    121 
    122 <procedure>(bind-seq-null? xpr)</procedure>
    123 
    124 sequence analog of null?
     59=== Procedures
     60
     61==== bind-pvars
     62
     63<procedure>(bind-pvars pat)</procedure>
     64
     65extracts the symbols from pat except the wildcard and checks for
     66duplicates along its way.
     67
     68==== bind-seq->list
     69
     70This is a generic procedure. It is closed over a local database which
     71contains the necessary transformers.
     72
     73<procedure>(bind-seq->list)</procedure>
     74
     75resets the internal database for lists only.
     76
     77<procedure>(bind-seq->list seq)</procedure>
     78
     79returns the pair of transformers corresponding to seq.
     80
     81<procedure>(bind-seq->list pat seq)</procedure>
     82
     83returns a list where the value of the possible dotted
     84argument is retransformed to the type of seq.
     85
     86<procedure>(bind-seq->list seq? seq->list list->seq)</procedure>
     87
     88adds support for a new sequence type with predicate seq? and
     89transformers seq->list and list->seq to the internal database.
    12590
    12691=== Binding macros
    12792
     93==== bind-set!
     94
     95<macro>(bind-set! pat seq)</macro>
     96
     97sets symbols of pat to corresponding subexpressions of seq.
     98
     99==== bind-define
     100
     101<macro>(bind-define pat seq)</macro>
     102
     103defines pattern variables of pat with values matching
     104subexpressions of seq. Alias to bind-set!
     105
    128106====  bind
    129107
    130 <macro>(bind pat seq (where fender ...) .. xpr ....)</macro>
     108<macro>(bind pat seq xpr ....)</macro>
    131109
    132110binds pattern variables of pat to subexpressions of seq and executes
    133 xpr .... in this context, provided all fenders return #t, if supplied.
    134 
    135 ==== bindable?
    136 
    137 <macro>(bindable? pat (where fender ...) ..)</macro>
    138 
    139 returns a unary predicate which checks, if its sequence argument matches
    140 the pattern argument, pat, of bindable? and passes all of its fenders
    141 (the syntax is slightly changed for consistency).
    142 
    143 ====  bind-case
    144 
    145 <macro>(bind-case seq (pat (where fender ...) .. xpr ....) ....)</macro>
    146 
    147 Matches seq against a series of patterns and executes the body of the
    148 first matching pattern satisfying fenders (if given).
    149 
    150 ==== bind-define
    151 
    152 <macro>(bind-define pat seq pat1 seq1 ... (where fender ...) ..)</macro>
    153 
    154 defines pattern variables of pat pat1 ... with values matching
    155 subexpressions of seq seq1 ... in one go
    156 
    157 ==== bind-set!
    158 
    159 <macro>(bind-set! pat seq pat1 seq1 ... (where fender ...) ..)</macro>
    160 
    161 sets symbols of pat pat1 ... to corresponding subexpressions of seq seq1 ...
    162 
    163 ==== bind-lambda
    164 
    165 <macro>(bind-lambda pat (where fender ...) .. xpr ....)</macro>
    166 
    167 combination of lambda and bind, one pattern argument
    168 
    169 ====  bind-lambda*
    170 
    171 <macro>(bind-lambda* pat (where fender ...) .. xpr ....)</macro>
    172 
    173 combination of lambda and bind, multiple pattern arguments
    174 
    175 ==== bind-case-lambda
    176 
    177 <macro>(bind-case-lambda (pat (where fender ...) .. xpr ....) ....)</macro>
    178 
    179 Combination of bind-case and lambda with one pattern argument
    180 
    181 ==== bind-case-lambda*
    182 
    183 <macro>(bind-case-lambda* (pat (where fender ...) .. xpr ....) ....)</macro>
    184 
    185 Combination of bind-case and lambda with multiple pattern arguments
    186 
    187 ==== bind-named
    188 
    189 <macro>(bind-named loop pat seq (where fender ...) .. xpr ....)</macro>
     111xpr .... in this context.
     112
     113==== bind*
     114
     115<macro>(bind* loop pat seq xpr ....)</macro>
    190116
    191117named version of bind.
     
    194120==== bindrec
    195121
    196 <macro>(bindrec pat seq (where fender ...) .. xpr ....)</macro>
    197 
     122<macro>(bindrec pat seq xpr ....)</macro>
     123
     124recursive version of bind:
    198125bind pattern variables of pat to subsequences of seq recursively
    199126
     127==== bindable?
     128
     129<macro>(bindable? pat)</macro>
     130
     131returns a unary predicate which checks, if its sequence argument matches
     132the pattern argument, pat, of bindable?
     133
     134====  bind-case
     135
     136<macro>(bind-case seq (pat xpr ....) ....)</macro>
     137
     138Matches seq against a series of patterns and executes the body of the
     139first matching pattern.
     140
     141==== bind-lambda
     142
     143<macro>(bind-lambda pat xpr ....)</macro>
     144
     145combination of lambda and bind, one pattern argument.
     146
     147====  bind-lambda*
     148
     149<macro>(bind-lambda* pat xpr ....)</macro>
     150
     151combination of lambda and bind, multiple pattern arguments
     152
     153==== bind-case-lambda
     154
     155<macro>(bind-case-lambda (pat xpr ....) ....)</macro>
     156
     157Combination of bind-case and lambda with one pattern argument
     158
     159==== bind-case-lambda*
     160
     161<macro>(bind-case-lambda* (pat xpr ....) ....)</macro>
     162
     163Combination of bind-case and lambda with multiple pattern arguments
     164
    200165====  bind-let
    201166
    202 <macro>(bind-let loop .. ((pat seq) ...) (where fender ...) .. xpr ....)</macro>
     167<macro>(bind-let loop .. ((pat seq) ...) xpr ....)</macro>
    203168
    204169like let, named and unnamed, but binds patterns to sequence templates.
     
    208173==== bind-let*
    209174
    210 <macro>(bind-let* ((pat seq) ...) (where fender ...) .. xpr ....)</macro>
     175<macro>(bind-let* ((pat seq) ...) xpr ....)</macro>
    211176
    212177like let*, but binds patterns to sequence templates
     
    214179==== bind-letrec
    215180
    216 <macro>(bind-letrec ((patseq) ...)  (where fender ...) .. xpr ....)</macro>
    217 
    218 like letrec, but binds patterns to sequence templates
     181<macro>(bind-letrec ((patseq) ...) xpr ....)</macro>
     182
     183like letrec, but binds patterns to sequence templates.
    219184
    220185==== bind/cc
     
    227192=== Requirements
    228193
    229 checks simple-exceptions
     194None
    230195
    231196=== Usage
     
    239204<enscript highlight=scheme>
    240205
    241 (import bindings)
     206(import bindings checks)
     207
     208;; reset local database to pseudolists only
     209(bind-seq->list)
     210;; add vector and string support
     211(bind-seq->list vector? vector->list list->vector)
     212(bind-seq->list string? string->list list->string)
    242213
    243214(let ((stack #f) (push! #f) (pop! #f))
     
    272243; -> '(1 2 3 4)
    273244
    274 (bind (x . y) '#(1 2 3 4) (list x y))
    275 ; -> '(1 #(2 3 4))
     245(bind (x . y) #(1 2 3 4) (list x y))
     246; -> (1 #(2 3 4))
    276247
    277248(bind (x (y (z u . v)) w) '(1 #(2 "foo") 4)
     
    283254; -> '(1 2 3 4 5 #(6))
    284255
    285 ((bind-lambda (a (b . C) . d)
    286    (list a b C d))
     256((bind-lambda (a (b . c) . d)
     257   (list a b c d))
    287258 '(1 #(20 30 40) 2 3))
    288259; -> '(1 20 #(30 40) (2 3))
    289260
    290 ((bind-lambda* ((a (b . C) . d) (e . f))
    291    (list a b C d e f))
    292  '(1 #(20 30 40) 2 3) '#(4 5 6))
     261((bind-lambda* ((a (b . c) . d) (e . f))
     262   (list a b c d e f))
     263 '(1 #(20 30 40) 2 3) #(4 5 6))
    293264; -> '(1 20 #(30 40) (2 3) 4 #(5 6))
    294265
    295 (bind-named loop (x (a . b) y) '(5 #(1) 0)
    296   (where (x integer?))
     266(bind* loop (x (a . b) y) '(5 #(1) 0)
     267  (>> x integer?)
    297268  (if (zero? x)
    298269    (list x a b y)
     
    300271; -> '(0 1 (1 1 1 1 1 . #()) 5)
    301272
    302 (bind-named loop (x y) '(5 0)
     273(bind* loop (x y) '(5 0)
    303274  (if (zero? x)
    304275    (vector x y)
    305276    (loop (vector (- x 1) (+ y 1)))))
    306 ; -> '#(0 5)
     277; -> #(0 5)
    307278
    308279(bind-let (((x y (z . w)) '(1 2 #(3 4 5))))
     
    313284  (((x y) z) '(#(1 2) 3))
    314285  (u (+ 2 2))
    315   ((v w) '#(5 6))
     286  ((v w) #(5 6))
    316287  )
    317288  (list x y z u v w))
     
    319290
    320291(bind-let loop (((a b) '(5 0)))
    321   (where (a integer?))
     292  (>> a integer?)
    322293  (if (zero? a)
    323294    (list a b)
     
    329300  ((z) '#(10))
    330301  )
    331   (where (x integer?) (y (list-of? integer?)) (z integer?))
     302  (>> x integer?) (>> y (list-of? integer?)) (>> z integer?)
    332303  (if (zero? z)
    333304    (list x y z)
     
    346317  (vector (list (lambda (m) (if (zero? m) #f (e? (- m 1)))))
    347318          (lambda (n) (if (zero? n) #t (o? (- n 1)))))
    348   (where (o? procedure?) (e? procedure?))
     319  (>> o? procedure?) (>> e? procedure?)
    349320  (list (o? 95) (e? 95)))
    350321; -> '(#t #f)
    351322
    352323(bind-letrec (
    353   ((o? (e?))
    354    (list (lambda (m) (if (zero? m) #f (e? (- m 1))))
    355          (vector (lambda (n) (if (zero? n) #t (o? (- n 1)))))))
     324  (o? (lambda (m) (if (zero? m) #f (e? (- m 1)))))
     325  ((e?) (vector (lambda (n) (if (zero? n) #t (o? (- n 1))))))
    356326  )
    357327  (list (o? 95) (e? 95)))
     
    361331; -> #t
    362332
    363 ((bindable? (a (b C) . d)) '(1 (2 3) . 4))
     333((bindable? (a (b c) . d)) '(1 (2 3) . 4))
    364334; -> #t
    365335
    366 ((bindable? (a (b C) . d)) '(1 #(2 3) 4 5))
     336((bindable? (a (b c) . d)) '(1 #(2 3) 4 5))
    367337; -> #t
    368338
    369 ((bindable? (a (b . C) . d)) '(1 (2 3) 4))
     339((bindable? (a (b . c) . d)) '(1 (2 3) 4))
    370340; -> #t
    371341
    372 ((bindable? (a (b . C) . d)) '#(1 2 3 4 5))
     342((bindable? (a (b . c) . d)) '#(1 2 3 4 5))
    373343; -> #f
    374344
    375 ((bindable? (a (b C) d)) '(1 (2 3) 4 5))
     345((bindable? (a (b c) d)) '(1 (2 3) 4 5))
    376346; -> #f
    377 
    378 ((bindable? (a b) (even? a)) '#(1 2))
    379 ; -> #f
    380347
    381348(bind-case '#(1 2)
     
    383350  ((a) (list a))
    384351  ((a b) (list a b))
    385   ((a b C) (list a b C)))
     352  ((a b c) (list a b c)))
    386353; -> '(1 2))
    387354
     
    407374
    408375((bind-case-lambda
    409    ((a (b . C) . d) (list a b C d))
    410    ((e . f) (where (e zero?)) e)
     376   ((a (b . c) . d) (list a b c d))
     377   ((e . f) (>> e zero?) e)
    411378   ((e . f) (list e f)))
    412379 '(1 2 3 4 5))
     
    414381
    415382((bind-case-lambda
    416    ((e . f) (where (e zero?)) f)
     383   ((e . f) (>> e zero?) f)
    417384   ((e . f) (list e f)))
    418  '#(0 2 3 4 5))
    419 ;-> '#(2 3 4 5))
     385 #(0 2 3 4 5))
     386;-> #(2 3 4 5))
    420387
    421388((bind-case-lambda
    422    ((a (b . C) . d) (list a b C d))
     389   ((a (b . c) . d) (list a b d))
    423390   ((e . f) (list e f)))
    424391 '(1 #(2 3 4) 5 6))
     
    426393
    427394((bind-case-lambda*
    428    (((a b C . d) (e . f))
    429     (list a b C d e f)))
    430  '(1 2 3) '#(4 5 6))
     395   (((a b . d) (e . f))
     396    (list a b d e f)))
     397 '(1 2 3) #(4 5 6))
    431398; -> '(1 2 3 () 4 #(5 6))
    432399
    433400((bind-case-lambda*
    434    (((a (b . C) . d) (e . f))
    435     (list a b C d e f)))
     401   (((a (b . c) . d) (e . f))
     402    (list a b c d e f)))
    436403 '(1 #(20 30 40) 2 3) '(4 5 6))
    437404; -> '(1 20 #(30 40) (2 3) 4 (5 6))
     
    441408== Last update
    442409
    443 Mar 06, 2019
     410Dec 13, 2019
    444411
    445412== Author
     
    479446
    480447== Version History
     448; 2.0 : complete rewrite, code simplified, where clause removed
    481449; 1.5 : prepared for lazy-pairs
    482450; 1.4 : dependency on checks removed
Note: See TracChangeset for help on using the changeset viewer.