A treelist represents a sequence of elements in a way that supports many operations in O(log N) time: accessing an element of the list by index, adding to the front of the list, adding to the end of the list, removing an element by index, replacing an element by index, appending lists, dropping elements from the start or end of the list, and extracting a sublist. More generally, unless otherwise specified, operations on a treelist of length N take O(log N) time. The base for the log in O(log N) is large enough that it’s effectively constant-time for many purposes. Treelists are currently implemented as RRB trees [Stucki15].
Treelists are primarily intended to be used in immutable form via racket/treelist, where an operation such as adding to the treelist produces a new treelist while the old one remains intact. A mutable variant of treelists is provided by racket/mutable-treelist, where a mutable treelist can be a convenient alternative to putting an immutable treelist into a box. Mutable treelist operations take the same time as immutable treelist operations, unless otherwise specified. Where the term “treelist” is used by itself, it refers to an immutable treelist.
An immutable or mutable treelist can be used as a single-valued sequence (see Sequences). The elements of the list serve as elements of the sequence. See also in-treelist and in-mutable-treelist . An immutable treelist can also be used as a stream.
Changed in version 8.15.0.3 of package base: Made treelists serializable.
Added in version 8.12.0.7 of package base.
This operation takes O(N log N) time to construct a treelist of N elements.
(treelist 1 "a" 'apple)
procedure
( make-treelist sizev)→treelist?
v:any/c
(treelist)
(treelist 'pear 'pear 'pear)
Added in version 8.12.0.11 of package base.
procedure
( treelist-empty? tl)→boolean?
tl:treelist?value
Although every empty treelist is equal? to empty-treelist , since a treelist can be chaperoned via chaperone-treelist , not every empty treelist is eq? to empty-treelist .
procedure
tl:treelist?
3
procedure
( treelist-ref tlpos)→any/c
tl:treelist?
1
'apple
treelist-ref: index is out of range
index: 3
valid range: [0, 2]
treelist: (treelist 1 "a" 'apple)
procedure
( treelist-first tl)→any/c
tl:treelist?procedure
( treelist-last tl)→any/c
tl:treelist?
1
'apple
procedure
( treelist-insert tlposv)→treelist?
tl:treelist?v:any/c
(treelist 1 "alpha" "a" 'apple)
(treelist 1 "a" 'apple "alpha")
Although the main operation to extend a pair list is cons to add to the front, treelists are intended to be extended by adding to the end with treelist-add , and treelist-add tends to be faster than treelist-cons .
(treelist 1 "a" 'apple "alpha")
(treelist "alpha" 1 "a" 'apple)
procedure
( treelist-delete tlpos)→treelist?
tl:treelist?
(treelist 1 'apple)
treelist-delete: index is out of range
index: 3
valid range: [0, 2]
treelist: (treelist 1 "a" 'apple)
procedure
( treelist-set tlposv)→treelist?
tl:treelist?v:any/c
(treelist 1 "b" 'apple)
procedure
( treelist-append tl...)→treelist?
tl:treelist?
(treelist 1 "a" 'apple 1 "a" 'apple)
(treelist 1 "a" 'apple "middle" 1 "a" 'apple)
(treelist 1 "a")
(treelist 'apple)
(treelist "a" 'apple)
(treelist 1)
procedure
( treelist-sublist tlnm)→treelist?
tl:treelist?
(treelist "a" 'apple)
procedure
( treelist-reverse tl)→treelist?
tl:treelist?
(treelist 'apple "a" 1)
procedure
( treelist-rest tl)→treelist?
tl:treelist?
The treelist-rest operation is efficient, but not as fast as rest or cdr . For iterating through a treelist, consider using treelist-ref or a for form with in-treelist , instead.
(treelist "a" 'apple)
procedure
( treelist->vector tl)→vector?
tl:treelist?procedure
( treelist->list tl)→list?
tl:treelist?procedure
( vector->treelist vec)→treelist?
vec:vector?procedure
( list->treelist lst)→treelist?
lst:list?
'#(1 "a" 'apple)
(treelist '#&1 '#&"a" '#&apple)
1
"a"
'apple
(treelist 2 2 4 2)
(treelist 1 3 5)
(treelist 1 3 5)
(treelist 2 2 4 2)
Added in version 8.15.0.6 of package base.
procedure
( treelist-member? tlv[eql?])→boolean?
tl:treelist?v:any/c
#t
#t
=: contract violation
expected: number?
given: "a"
"a"
'apple
1
procedure
( treelist-index-of tlv[eql?])
tl:treelist?v:any/c
0
1
2
#f
Added in version 8.15.0.6 of package base.
procedure
v:any/c
(treelist "a" "b" "c" "d" "e")
(treelist "a")
Added in version 8.15.0.6 of package base.
procedure
( treelist-append* tlotl)→treelist?
(treelist "a" "b" "c" (treelist "d") "e")
Added in version 8.15.0.6 of package base.
procedure
less-than?[ #:keykeytl:treelist?
(treelist "a" "q" "x")
procedure
( in-treelist tl)→sequence?
tl:treelist?
'("x!" "a!" "q!")
procedure
(treelist 1 "a" 'apple)
(treelist 1 "a" 'apple)
(treelist 1 "a" 'apple)
(treelist 1 2 3 4 5)
(treelist 0 1 2 3 4 5 6 7 8 9)
Added in version 8.15.0.6 of package base.
syntax
( for/treelist (for-clause...)body-or-break...body)
syntax
( for*/treelist (for-clause...)body-or-break...body)
i)(treelist 0 1 2 3 4 5 6 7 8 9)
procedure
#:statestate[ #:state-keystate-key]#:refref-proc#:setset-proc#:insertinsert-proc#:deletedelete-proc#:taketake-proc#:dropdrop-proc#:appendappend-proc#:prependprepend-proc[ #:append2append2-proc]propprop-val......)tl:treelist?state:any/c= #fprop-val:any/c
The ref-proc procedure must accept tl, an index passed to treelist-ref , the value that treelist-ref on tl produces for the given index, and the current chaperone state; it must produce a chaperone replacement for the value, which is the result of treelist-ref on the chaperone.
The set-proc procedure must accept tl, an index passed to treelist-set , the value provided to treelist-set , and the current chaperone state; it must produce two values: a chaperone replacement for the value, which is used in the result of treelist-set on the chaperone, and an updated state. The result of treelist-set is chaperoned with the same procedures and properties as tl, but with the updated state.
The insert-proc procedure is like set-proc, but for inserting via treelist-insert .
The delete-proc, take-proc, and drop-proc procedures must accept tl, the index or count for deleting, taking or dropping, and the current chaperone state; they must produce an updated state. The result of treelist-delete , treelist-take , or treelist-drop is chaperoned with the same procedures and properties as tl, but with the updated state.
The append-proc procedure must accept tl, a treelist to append onto tl, and the current chaperone state; it must produce a chaperone replacement for the second treelist, which is appended for the result of treelist-append on the chaperone, and an updated state. The result of treelist-append is chaperoned with the same procedures and properties as tl, but with the updated state.
The prepend-proc procedure must accept a treelist being append with tl, tl, and the current chaperone state; it must produce a chaperone replacement for the first treelist, which is prepended for the result of treelist-append on the chaperone, and an updated state. The result of treelist-append is chaperoned with the same procedures and properties as tl, but with the updated state.
The append2-proc procedure is optional and similar to append-proc, but when it is non-#f, append2-proc is used instead of append-proc when a second argument to treelist-append is chaperoned with the same state-key. In that case, the second argument to append2-proc is the second argument with a state-key chaperone wrapper removed, and with that chaperone’s state as the last argument to append2-proc.
When two chaperoned treelists are given to treelist-append and append2-proc is not used, then the append-proc of the first treelist is used, and the result of append-proc will still be a chaperone whose prepend-proc is used. If the result of prepend-proc is a chaperone, then that chaperone’s append-proc is used, and so on. If prepend-proc and append-proc keep returning chaperones, it is possible that no progress will be made.
#:state'ignored-statev)state)state)state)(treelist 1 "a" 'apple)
A mutable treelist is like an immutable treelist in a box, where operations that change the mutable treelist replace the treelist in the box. As a special case, mutable-treelist-set! on an unimpersonated mutable treelist modifies the treelist representation within the boxed value. This model of a mutable treelist explains its behavior in the case of concurrent modification: concurrent mutable-treelist-set! operations for different positions will not interefere, but races with other operations or on impersonated mutable treelists will sometimes negate one of the modifications. Concurrent modification is thus somewhat unpredictable but still safe, and it is not managed by a lock.
A mutable treelist is not a treelist in the sense of treelist? , which recognizes only immutable treelists. Operations on a mutable treelist have the same time complexity as corresponding operations on an immutable treelist unless otherwise noted.
Added in version 8.12.0.7 of package base.
procedure
v:any/c
procedure
( mutable-treelist v...)→mutable-treelist?
v:any/c
(mutable-treelist 1 "a" 'apple)
procedure
(mutable-treelist "a" "a" "a")
procedure
tl:treelist?procedure
(mutable-treelist 3 "a")
(mutable-treelist 3 "a")
procedure
( mutable-treelist-snapshot tl[nm])→treelist?
> snap(treelist 1 "a" 'apple)
(treelist "a" 'apple)
(treelist "a")
> items(mutable-treelist 'apple)
> snap(treelist 1 "a" 'apple)
procedure
procedure
3
4
procedure
( mutable-treelist-ref tlpos)→any/c
1
'apple
mutable-treelist-ref: index is out of range
index: 3
valid range: [0, 2]
mutable treelist: (mutable-treelist 1 "a" 'apple)
procedure
( mutable-treelist-first tl)→any/c
procedure
( mutable-treelist-last tl)→any/c
1
'apple
procedure
( mutable-treelist-insert! tlposv)→void?
v:any/c
> items(mutable-treelist 1 "alpha" "a" 'apple)
> items(mutable-treelist "before" 1 "a" 'apple "after")
procedure
( mutable-treelist-delete! tlpos)→void?
> items(mutable-treelist 1 'apple)
procedure
( mutable-treelist-set! tlposv)→void?
v:any/c
> items(mutable-treelist 1 "b" 'apple)
procedure
( mutable-treelist-append! tlother-tl)→void?
procedure
( mutable-treelist-prepend! tlother-tl)→void?
> items(mutable-treelist 1 "a" 'apple 'more 'things)
> items(mutable-treelist 0 "b" 'banana 1 "a" 'apple 'more 'things)
> items(mutable-treelist
0
"b"
'banana
1
"a"
'apple
'more
'things
0
"b"
'banana
1
"a"
'apple
'more
'things)
Changed in version 8.15.0.11 of package base: Added mutable-treelist-prepend! .
procedure
procedure
> items(mutable-treelist 1 "a")
> items(mutable-treelist 1)
procedure
( mutable-treelist-sublist! tlnm)→void?
> items(mutable-treelist "a" 'apple)
procedure
> items(mutable-treelist 'pie 'apple "a" 1)
procedure
procedure
( mutable-treelist->list tl)→list?
procedure
vec:vector?procedure
lst:list?
'#(1 "a" 'apple)
procedure
( mutable-treelist-map! tlproc)→void?
> items(mutable-treelist '#&1 '#&"a" '#&apple)
procedure
( mutable-treelist-for-each tlproc)→void?
1
"a"
'apple
procedure
( mutable-treelist-member? tlv[eql?])→boolean?
v:any/c
#t
#t
procedure
( mutable-treelist-find tlpred)→any/c
"a"
'apple
procedure
less-than?[ #:keykey
> items(mutable-treelist "a" "q" "x")
procedure
( in-mutable-treelist tl)→sequence?
'("x!" "a!" "q!")
syntax
( for/mutable-treelist maybe-length(for-clause...)body-or-break...body)
syntax
( for*/mutable-treelist maybe-length(for-clause...)body-or-break...body)
(mutable-treelist 0 1 2 3 4 5 6 7 8 9)
(mutable-treelist 0 1 2 3 4 5 6 7 8 9 0 0 0 0 0)
(mutable-treelist 0 1 2 3 4 5 6 7 8 9 'a 'a 'a 'a 'a)
procedure
#:refref-proc#:setset-proc#:insertinsert-proc#:appendappend-proc[ #:prependprepend-proc]propprop-val......)prop-val:any/c
procedure
#:refref-proc#:setset-proc#:insertinsert-proc#:appendappend-proc[ #:prependprepend-proc]propprop-val......)prop-val:any/c