You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sugar/scribblings/list.scrbl

231 lines
7.5 KiB
Racket

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#lang scribble/manual
@(require scribble/eval (for-label racket sugar))
@(define my-eval (make-base-eval))
@(my-eval `(require sugar racket/list))
@title{Lists}
@defmodule[#:multi (sugar/list (submod sugar/list safe))]
@defproc[
(trimf
[lst list?]
[pred procedure?])
list?]
Drop elements from each end of @racket[_lst] that satisfy @racket[_pred]. Exactly equivalent to @racket[(dropf-right (dropf _lst _pred) _pred)].
@examples[#:eval my-eval
(trimf '(1 2 3 a b c 4 5 6) integer?)
(trimf '(1 2 3 a b c) integer?)
(trimf '(a b c) integer?)
(trimf '(a b c 1 2 3 d e f) integer?)]
@defproc[
(filter-split
[lst list?]
[pred procedure?])
(listof list?)]
Like @racket[string-split], but for lists. Drop elements from anywhere in @racket[_lst] that satisfy @racket[_pred] ends, middle, you name it and return a list of the sublists that remain.
@examples[#:eval my-eval
(filter-split '(1 a b c 2 d e f 3) integer?)
(filter-split '(1 a b c 2 d e f 3) (compose not integer?))
(filter-split '(a b c 1 2 3 d e f) integer?)
(filter-split '(a b c 1 2 3 d e f) (compose not integer?))]
@defproc[
(slice-at
[lst list?]
[len (and/c integer? positive?)]
[force? boolean? #f])
(listof list?)]
Divide @racket[_lst] into sublists of length @racket[_len]. If @racket[_lst] cannot be divided evenly by @racket[_len], the last sublist will be shorter. If this displeases you, set @racket[_force?] to @racket[#t] and a stumpy final sublist will be ignored.
@examples[#:eval my-eval
(slice-at (range 5) 1)
(slice-at (range 5) 2)
(slice-at (range 5) 2 #t)
(slice-at (range 5) 3)
(slice-at (range 5) 5)
(slice-at (range 5) 5 #t)
(slice-at (range 5) 100000)
(slice-at (range 5) 100000 #t)]
@defproc[
(slicef
[lst list?]
[pred procedure?])
(listof list?)]
Divide @racket[_lst] into sublists that are homogeneously @racket[_pred] or not @racket[_pred]. If none of the elements match @racket[_pred], there is no slice to be made, and the result is the whole input list.
@examples[#:eval my-eval
(slicef '(1 2 2 1 2) even?)
(slicef (range 5) odd?)
(slicef (range 5) string?)]
@defproc[
(slicef-at
[lst list?]
[pred procedure?]
[force? boolean? #f])
(listof list?)]
Divide @racket[_lst] into sublists starting with elements matching @racket[_pred]. The first element of the first sublist may not match @racket[_pred]. Or, if you really & truly want only the sublists starting with an element matching @racket[_pred], set @racket[_force?] to @racket[#t].
@examples[#:eval my-eval
(slicef-at (range 5) even?)
(slicef-at '(1 2 2 1 2) even?)
(slicef-at '(1 2 2 1 2) even? #t)
(slicef-at (range 5) odd?)
(slicef-at (range 5) odd? #t)]
@defproc[
(slicef-after
[lst list?]
[pred procedure?])
(listof list?)]
Divide @racket[_lst] into sublists ending with elements matching @racket[_pred]. (Distinct from @racket[slicef-at], which gives you sublists that @italic{start} with elements matching @racket[_pred].) If none of the elements match @racket[_pred], there is no slice to be made, and the result is the whole input list.
@examples[#:eval my-eval
(slicef-after '(1 2 2 1 2) even?)
(slicef-after (range 5) odd?)
(slicef-after (range 5) string?)]
@defproc[
(frequency-hash
[lst list?])
hash?]
Count the frequency of each element in @racket[_lst], and return a hash whose keys are the unique elements of @racket[_lst], and each value is the frequency of that element within @racket[_lst].
@examples[#:eval my-eval
(frequency-hash '(a b b c c c))
(frequency-hash '(c b c a b c))
]
@defproc[
(members-unique?
[container (or/c list? vector? string?)])
boolean?]
Return @racket[#t] if every element in @racket[_container] is unique, otherwise @racket[#f].
@examples[#:eval my-eval
(members-unique? '(a b c d e f))
(members-unique? '(a b c d e f a))
]
@defproc[
(members-unique?/error
[container (or/c list? vector? string?)])
boolean?]
Same as @racket[members-unique?], but if the members are not unique, raises a descriptive error rather than returning @racket[#f].
@examples[#:eval my-eval
(members-unique?/error '(a b c d e f))
(members-unique?/error '(a b c d e f a))
(members-unique?/error '(a b c d e f a b))
]
@defform[(values->list values)]
Convert @racket[_values] to a simple list.
@examples[#:eval my-eval
(split-at '(a b c d e f) 3)
(values->list (split-at '(a b c d e f) 3))
]
@defproc[
(sublist
[lst list?]
[start-idx (and/c integer? (not/c negative?))]
[end-idx (and/c integer? (not/c negative?))])
list?]
Return a sublist of the @racket[_lst] starting with item @racket[_start-idx] and ending one item @bold{before} item @racket[_end-idx]. (Similar to how list slices are denominated in Python.) Thus the maximum value for @racket[_end-idx] is @racketfont{(length @racket[_lst])}. Errors will be triggered by nonsensical values for @racket[_end-idx].
Bear in mind that @racket[sublist] is built for convenience, not performance. If you need to do a lot of random access into the middle of an ordered sequence of items, you'd be better off putting them into a @racket[vector] and using @racket[vector-copy].
@examples[#:eval my-eval
(sublist '(0 1 2 3 4 5 6 7 8) 0 8)
(sublist '(0 1 2 3 4 5 6 7 8) 8 9)
(sublist '(0 1 2 3 4 5 6 7 8) 2 5)
(sublist '(0 1 2 3 4 5 6 7 8) 5 2)
(sublist '(0 1 2 3 4 5 6 7 8) 2 10)
]
@defproc[
(break-at
[lst list?]
[indexes (or/c integer? (listof integer?))])
(listof list?)]
Break @racket[_lst] into smaller lists at the index positions in @racket[_indexes]. If a single integer value is given for @racket[_indexes], it's treated as a one-element list. Errors will arise if a breakpoint index exceeds the length of the list, or if the breakpoints are not increasing.
@examples[#:eval my-eval
(break-at '(0 1 2 3 4 5 6 7 8) 3)
(break-at '(0 1 2 3 4 5 6 7 8) '(3))
(break-at '(0 1 2 3 4 5 6 7 8) '(3 6))
(break-at '(0 1 2 3 4 5 6 7 8) '(3 6 8))
(break-at '(0 1 2 3 4 5 6 7 8) '(3 6 8 10))
]
@defproc[
(shift
[lst list?]
[how-far integer?]
[fill-item any/c #f]
[cycle? boolean? #f])
list?]
Move the items in @racket[_lst] to the right (if @racket[_how-far] is positive) or left (if @racket[_how-far] is negative). By default, vacated spaces in the list are filled with @racket[_fill-item]. But if @racket[_cycle?] is true, elements of the list wrap around (and @racket[_fill-item] is ignored). Either way, the result list is always the same length as the input list. (If you don't care about the lengths being the same, you probably want @racket[take] or @racket[drop] instead.) If @racket[_how-far] is 0, return the original list. If @racket[_how-far] is bigger than the length of @racket[_lst], raise an error.
@examples[#:eval my-eval
(define xs (range 5))
(shift xs 2)
(shift xs -2 0)
(shift xs 2 'boing)
(shift xs 2 'boing #t)
(shift xs 0)
(shift xs 42)
]
@defproc[
(shifts
[lst list?]
[how-far (listof integer?)]
[fill-item any/c #f]
[cycle? boolean? #f])
(listof list?)]
Same as @racket[shift], but @racket[_how-far] is a list of integers rather than a single integer, and the result is a list of lists rather than a single list.
@examples[#:eval my-eval
(define xs (range 5))
(shifts xs '(-2 2))
(shifts xs '(-2 2) 0)
(shifts xs '(-2 2) 'boing)
(shifts xs '(-2 2) 'boing #t)
]
@defproc[
(shift/values
[lst list?]
[how-far (or/c integer? (listof integer?))]
[fill-item any/c #f])
any]
When @racket[_how-far] is a single integer, same as @racket[shift], but the resulting list is returned as values. When @racket[_how-far] is a list of integers, same as @racket[shifts], but the resulting lists are returned as multiple values rather than as a list of lists.
@examples[#:eval my-eval
(define xs (range 5))
(shift xs 1)
(shift/values xs 1)
(shifts xs '(-1 0 1))
(shift/values xs '(-1 0 1))
]