split-xlist.scrbl (4132B)
1 #lang scribble/manual 2 @require[phc-toolkit/scribblings/utils 3 scribble/examples 4 @for-label[xlist 5 typed/racket/base]] 6 7 @title{Splitting an xlist in its constituent sublists} 8 @(declare-exporting xlist) 9 10 @(define make-eval (make-eval-factory '(xlist type-expander) 11 #:lang 'typed/racket)) 12 13 @defform*[#:kind "match-expander" 14 #:literals (^ * + - ∞) 15 [(split-xlist pat τᵢ ...) 16 (split-xlist pat τᵢ ... . rest) 17 (split-xlist pat τᵢ ... #:rest rest)] 18 #:grammar 19 [(τᵢ type 20 repeated-type) 21 (repeated-type (code:line type ^ repeat) 22 (code:line type ^ {repeat}) 23 (code:line type {repeat}) 24 (code:line type superscripted-repeat) 25 (code:line type *) 26 (code:line type +) 27 (code:line superscripted-id)) 28 (repeat (code:line once) 29 (code:line nat) 30 (code:line nat +) 31 (code:line +) 32 (code:line nat - nat) 33 (code:line nat - ∞) 34 (code:line nat -) 35 (code:line - nat) 36 (code:line -) 37 (code:line - ∞) 38 (code:line *))] 39 #:contracts 40 [(nat (syntax/c exact-nonnegative-integer?))]]{ 41 This match pattern splits an xlist into a list of lists, and matches the 42 result against @racket[pat]. Each repeated element of the xlist is extracted 43 into one of these sublists. The type for each sublist is determined based on 44 the element's type and its @racket[_repeat]: 45 @itemlist[ 46 @item{If the @racket[_repeat] for that element is @racket[once], then the 47 element is inserted directly, without nesting it within a sublist. In 48 contrast, it the @racket[_repeat] were @racket[1], the element would be 49 inserted in a sublist of length one.} 50 @item{If the @racket[_repeat] for that element is @racket[*] or an 51 equivalent, the type of the sublist will be @racket[(Listof type)]} 52 @item{If the @racket[_repeat] for that element is @racket[_n +] or an 53 equivalent, the type of the sublist will be @racket[(xList type ^ _n +)]} 54 @item{If the @racket[_repeat] for that element is @racket[_n] or an 55 equivalent, the type of the sublist will be @racket[(xList type ^ _n)]} 56 @item{If the @racket[_repeat] for that element is @racket[_from - _to] or an 57 equivalent, the type of the sublist will be 58 @racket[(xList type ^ _from - _to)]} 59 @item{The @racket[#:rest] or dotted rest is included as the last element of 60 the list matched against @racket[pat]. If the first form without a rest type 61 is used, the list matched against @racket[pat] still contains @racket['()] as 62 a last element: 63 @examples[#:eval (make-eval) 64 (match '(1 2 3) 65 [(split-xlist (list (list a) (list b c) (? null?)) 66 Number¹ Number⃰) 67 (vector c b a)])]}] 68 69 Note that @racket[split-xlist] assumes the value it is matched against has 70 the type @racket[(xlist τᵢ ... maybe-rest)], but does not apply 71 @racket[(? (make-predicate (xlist τᵢ ... maybe-rest)))] to the value itself. 72 The rationale is that the @racket[make-predicate] may fail at compile-time if 73 it cannot generate a contract for the given type. In some cases, however 74 @racket[split-xlist] will still manage to successfully generate the match 75 pattern, and can be used on its own, provided that the value is statically 76 known to be of the right type. 77 78 It is therefore recommended to use @racket[split-xlist] as follows when the 79 type of the value is not known to be acceptable by @racket[split-xlist]: 80 81 @examples[#:eval (make-eval) 82 (define v : Any '(1 2 3)) 83 (match '(1 2 3) 84 [(and (? (make-predicate (xlist Number¹ Number⃰))) 85 (split-xlist (list (list a) (list b c) (? null?)) 86 Number¹ Number⃰)) 87 'success])]}