www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

xlist.scrbl (13358B)


      1 #lang scribble/manual
      2 @require[scribble-enhanced/with-manual
      3          xlist/scribble-enhanced
      4          scribble-math
      5          racket/require
      6          @for-label[xlist
      7                     (subtract-in typed/racket/base match-string)
      8                     (only-in syntax/parse ...+)
      9                     match-string]]
     10 
     11 @title[#:style (with-html5 manual-doc-style)]{xlist}
     12 @author[@author+email["Suzanne Soy" "racket@suzanne.soy"]]
     13 
     14 @(define ddd (racket ...))
     15 
     16 @defmodule[xlist]
     17 
     18 Fancy lists, with bounded or unbounded repetition of elements. Can be used as a
     19 type or match pattern.
     20 
     21 To use the type expander, you must first require the
     22 @racketmodname[type-expander] library.
     23 
     24 @deftogether[
     25  [@defform*[#:kind "type-expander"
     26             [(xList τᵢ ...)
     27              (xList τᵢ ... . rest)
     28              (xList τᵢ ... #:rest rest)]]
     29   @defform*[#:kind "type-expander"
     30             #:literals (^ * + - ∞ once)
     31             [(xlist τᵢ ...)
     32              (xlist τᵢ ... . rest)
     33              (xlist τᵢ ... #:rest rest)]
     34             #:grammar
     35             [(τᵢ type
     36                  repeated-type)
     37              (repeated-type (code:line type ^ repeat)
     38                             (code:line type ^ {repeat})
     39                             (code:line type {repeat})
     40                             (code:line type superscripted-repeat)
     41                             (code:line type *)
     42                             (code:line type +)
     43                             (code:line superscripted-id))
     44              (repeat (code:line once)
     45                      (code:line nat)
     46                      (code:line nat +)
     47                      (code:line +)
     48                      (code:line nat - nat)
     49                      (code:line nat - ∞)
     50                      (code:line nat -)
     51                      (code:line - nat)
     52                      (code:line -)
     53                      (code:line - ∞)
     54                      (code:line *))]
     55             #:contracts
     56             [(nat (syntax/c exact-nonnegative-integer?))]]]]{
     57  The notation @racket[type ^ _n], where @racket[_n] is a number, indicates that
     58  the given type should be repeated @racket[_n] times within the list. Therefore,
     59  the following two types are equivalent:
     60  
     61  @racketblock[
     62  (xList Number ^ 3 Symbol String ^ 2)
     63  
     64  (List Number Number Number Symbol String String)]
     65 
     66  The notation @racket[type *] indicates that the given type may be repeated zero
     67  or more times. Therefore, the following two types are equivalent:
     68 
     69  @racketblock[
     70  (xList Number * Symbol String *)
     71  
     72  (Rec R1 (U (Pairof Number R1)
     73             (List* Symbol (Rec R2 (U (Pairof String R2)
     74                                      Null)))))]
     75 
     76  The notation @racket[type ^ _n +] indicates that the given type may be repeated
     77  @racket[_n] or more times. Therefore, the following two types are equivalent:
     78  
     79  @racketblock[
     80  (xList Number ^ {2 +} String)
     81  
     82  (List* Number Number (Rec R1 (U (Pairof Number R1)
     83                                  (List String))))]
     84 
     85  When the number preceding @racket[+] is omitted, it defaults to @racket[1].
     86 
     87  The notation @racket[type ^ once] yields the same type as @racket[type ^ 1],
     88  but other forms recognise @racket[once] and treat it specially. For example,
     89  @racket[xlist-split] splits the corresponding element as a standalone value,
     90  not as a list of length one.
     91 
     92  The notation @racket[type ^ _n - _m] indicates that the given type may be
     93  repeated between @racket[_n] (inclusive) and @racket[_m] (inclusive) times.
     94  Therefore, the following two types are equivalent:
     95  
     96  @racketblock[
     97  (xList Number ^ {2 - 5} String)
     98  
     99  (U (List Number Number String)
    100     (List Number Number Number String)
    101     (List Number Number Number Number String)
    102     (List Number Number Number Number Number String))]
    103 
    104  Be aware that the tail of the @racket[xList] following the use of
    105  @racket[type ^ _n - _m] is repeated @${n - m} times, so if the tail itself
    106  contains uses of @racket[-], the resulting macro-expanded type will be huge,
    107  and may easily make Typed/Racket run out of memory, or slow down the type
    108  checking.
    109 
    110  If the first bound is omitted, it defaults to @racket[0], and if the second
    111  bound is omitted, it defaults to @racket[∞]. This means that @racket[-] on its
    112  own is equivalent to @racket[*], but the latter form is preferred.
    113  
    114  The @racket[superscripted-repeat] is a representation of @racket[repeat] using
    115  superscripted unicode characters, without spaces (i.e. the
    116  @racket[superscripted-repeat] is a single identifier):
    117 
    118  @itemlist[
    119  @item{Digits are replaced by their unicode superscripted counterparts
    120    @elem[#:style 'tt "⁰¹²³⁴⁵⁶⁷⁸⁹"]}
    121  @item{@racket[+] and @racket[-] are replaced by their unicode superscripted
    122    counterparts, respectively @elem[#:style 'tt "⁺"] and @elem[#:style 'tt "⁻"]}
    123  @item{@racket[*] is replaced by the unicode character ``COMBINING ASTERISK
    124    ABOVE'' @tt{ ⃰} (code point U+20F0)}
    125  @item{@racket[∞] is always omitted, as @racket[_n - ∞] and @racket[- ∞] are
    126    equivalent to @racket[_n -] and @racket[0 -]}]
    127                                     
    128  A @racket[superscripted-id] is a type identifier ending with a sequence of
    129  characters which would otherwise be valid for @racket[superscripted-repeat]. In
    130  other words, if the @racket[type] is an identifier, the type and the
    131  @racket[superscripted-repeat] can be coalesced into a single identifier.
    132    
    133  The identifier @racket[String³] is equivalent to the notations
    134  @racket[String ³] (with a space between the identifier and the @racket[³]) and
    135  @racket[String ^ 3].
    136 
    137  Similarly, the identifier @racket[String⃰] is equivalent to the notations
    138  @racket[String  ⃰] (with a space between the identifier and the @racket[ ⃰]),
    139  @racket[String ^ *] (using a regular asterisk, i.e. the multiplication function
    140  in Racket) and @racket[String *] (using a regular asterisk, i.e. the
    141  multiplication function in Racket).
    142 
    143  The same logic applies to the other cases.}
    144 
    145 @defform*[#:kind "match-expander"
    146           #:link-target? #f
    147           #:literals (^ * + - ...+ ∞)
    148           [(xlist patᵢ ...)
    149            (xlist patᵢ ... . rest)
    150            (xlist patᵢ ... #:rest rest)]
    151           #:grammar
    152           [(patᵢ pattern-or-spliced
    153                  repeated-pattern
    154                  spliced-pattern)
    155            (pattern-or-spliced pattern
    156                                spliced-pattern)
    157            (spliced-pattern ,@pattern)
    158            (repeated-pattern (code:line pattern-or-spliced ^ repeat)
    159                              (code:line pattern-or-spliced ^ {repeat})
    160                              (code:line pattern-or-spliced superscripted-repeat)
    161                              (code:line pattern-or-spliced *)
    162                              (code:line pattern-or-spliced +)
    163                              (code:line pattern-or-spliced ooo)
    164                              (code:line superscripted-id))
    165            (repeat (code:line once)
    166                    (code:line nat)
    167                    (code:line nat +)
    168                    (code:line +)
    169                    (code:line nat - nat)
    170                    (code:line nat - ∞)
    171                    (code:line nat -)
    172                    (code:line - nat)
    173                    (code:line - ∞)
    174                    (code:line -)
    175                    (code:line *)
    176                    (code:line ooo))
    177            (ooo #,ddd
    178                 ..k
    179                 ____
    180                 ___k
    181                 ...+)]
    182           #:contracts
    183           [(nat (syntax/c exact-nonnegative-integer?))]]{
    184                                     
    185  This match expander works like the @racket[xList] type expander, but instead
    186  controls the repetition of match patterns. The repeated patterns are not
    187  literally copied, as this would likely cause errors related to duplicate
    188  attributes. Instead, the @racket[repeat] forms control the number of times a
    189  pattern may be bound, like @racket[...] does.
    190 
    191  If the @racket[_repeat] is @racket[once], or if the pattern does not have a
    192  @racket[_repeat], then the pattern is not put under ellipses, so that
    193  @racket[(match '(42) [(xlist a ^ once) a])] returns @racket[42], whereas
    194  @racket[(match '(42) [(xlist a ^ 1) a])] returns @racket['(42)].
    195 
    196  For convenience and compatibility with existing match patterns, the following
    197  equivalences are provided:
    198  @itemlist[
    199  @item{@racket[...] is equivalent to @racket[*]}
    200  @item{@racket[_..k] is equivalent to @racket[_k +]}
    201  @item{@racket[____] is equivalent to @racket[*]}
    202  @item{@racket[___k] is equivalent to @racket[_k +]}
    203  @item{@racket[...+] is equivalent to @racket[+]}]
    204 
    205  Additionally, when @RACKET[#,@pattern] appears as one of the @racket[xlist]
    206  elements, the given @racket[pattern] may match any number of elements in the
    207  list. This is implemented in terms of @racket[append] from the
    208  @racketmodname[match-string] library.
    209 
    210  The following two match patterns are therefore equivalent:
    211 
    212  @racketblock[
    213  (xlist number?³⁻⁵ ,@(list-no-order number? string?) symbol?⁺)
    214  
    215  (append (and (list number? ...) (app length (? (between/c 3 5))))
    216          (list-no-order number? string?)
    217          (list symbol? ..1))]
    218 
    219  Applying a repeat indicator on a splice is not supported yet, i.e.
    220  @racket[(xlist ,@(list-no-order number? string?)⁵)] will not work.
    221 
    222  @emph{Note :} Typed/Racket's type inference is not strong enough (yet) to
    223  support some match patterns, and there is no @elem[#:style 'tt "typed/match"]
    224  library which would help with that (yet). This means that although by
    225  construction @racket[xlist] tries to avoid generating such patterns, a few of
    226  the patterns supported by @racket[xlist] will not work in
    227  @racketmodname[typed/racket] (rest values and spliced lists are the most
    228  likely to cause problems). As an alternative, try the @racket[split-xlist]
    229  pattern, which produces code which should propagate type information to the
    230  different sub-lists.}
    231 
    232 @;{This is completely wrong.
    233  @defform*[#:link-target? #f
    234  #:literals (^ *)
    235  [(xlist τᵢ ... maybe-τⱼ τₖ ... maybe-τₙ)
    236   (xlist τᵢ ... τₘᵥ)]
    237  #:grammar
    238  [(τᵢ type
    239       fixed-repeated-type)
    240   (τₘᵥ mandatory-variadic-repeated-type)
    241   (maybe-τⱼ (code:line)
    242             mandatory-bounded-variadic-repeated-type)
    243   (τₖ optional-bounded-variadic-repeated-type)
    244   (maybe-τₙ (code:line)
    245             optional-variadic-repeated-type)
    246   (fixed-repeated-type
    247    (code:line type ^ fixed-repeat)
    248    (code:line type ^ {fixed-repeat})
    249    (code:line type {fixed-repeat})
    250    (code:line type superscripted-fixed-repeat)
    251    (code:line superscripted-fixed-id))
    252   (mandatory-bounded-variadic-repeated-type
    253    (code:line type ^ mandatory-bounded-variadic-repeat)
    254    (code:line type ^ {mandatory-bounded-variadic-repeat})
    255    (code:line type {mandatory-bounded-variadic-repeat})
    256    (code:line type superscripted-mandatory-bounded-variadic-repeat)
    257    (code:line superscripted-mandatory-bounded-variadic-id))
    258   (optional-bounded-variadic-repeated-type
    259    (code:line type ^ optional-bounded-variadic-repeat)
    260    (code:line type ^ {optional-bounded-variadic-repeat})
    261    (code:line type {optional-bounded-variadic-repeat})
    262    (code:line type superscripted-optional-bounded-variadic-repeat)
    263    (code:line superscripted-optional-bounded-variadic-id))
    264   (mandatory-variadic-repeated-type
    265    (code:line type ^ mandatory-variadic-repeat)
    266    (code:line type ^ {mandatory-variadic-repeat})
    267    (code:line type {mandatory-variadic-repeat})
    268    (code:line type superscripted-mandatory-variadic-repeat)
    269    (code:line superscripted-mandatory-variadic-id)
    270    (code:line type +))
    271   (optional-variadic-repeated-type
    272    (code:line type ^ optional-variadic-repeat)
    273    (code:line type ^ {optional-variadic-repeat})
    274    (code:line type {optional-variadic-repeat})
    275    (code:line type superscripted-optional-variadic-repeat)
    276    (code:line superscripted-optional-variadic-id)
    277    (code:line type *))
    278   (fixed-repeat (code:line nat)
    279                 (code:line from - to (code:comment "from = to")))
    280   (mandatory-bounded-variadic-repeat (code:line nat - nat))
    281   (optional-bounded-variadic-repeat (code:line 0 - nat)
    282                                     (code:line - nat))
    283   (mandatory-variadic-repeat (code:line nat +)
    284                              (code:line +)
    285                              (code:line nat -)
    286                              (code:line nat - ∞))
    287   (optional-variadic-repeat (code:line 0 - ∞)
    288                             (code:line 0 -)
    289                             (code:line - ∞)
    290                             (code:line -)
    291                             (code:line *))]]{
    292   Macro form which returns a builder function for a list with the given type.
    293   The simplified syntax compared to @racket[xList] is due to the fact that there
    294   are some function types that Typed/Racket cannot express (yet).}
    295 }
    296 
    297 @defproc[(normalize-xlist-type [stx syntax?] [context syntax?]) syntax?]{
    298  Normalizes the xlist type. The normalized form has one type followed by ^
    299  followed by a repeat within braces (a @racket[type] without a repeat is
    300  transformed into @racket[type ^ {once}]) for each position in the original
    301  type. It always finishes with #:rest rest-type. This function also performs a
    302  few simplifications on the type, like transforming @racket[^ {3 -}] into
    303  @racket[^ {3 +}], and transforming @racket[^ {0 -}] into @racket[^ {*}].}
    304 
    305 @include-section{split-xlist.scrbl}
    306 @include-section{xlist-untyped.scrbl}
    307 @include-section{identifiers.scrbl}