// Package vector implements persistent vector. // // This is a Go clone of Clojure's PersistentVector type // (https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/PersistentVector.java). // For an introduction to the internals, see // https://hypirion.com/musings/understanding-persistent-vector-pt-1.
package vector import ( ) const ( chunkBits = 5 nodeSize = 1 << chunkBits tailMaxLen = nodeSize chunkMask = nodeSize - 1 ) // Vector is a persistent sequential container for arbitrary values. It supports // O(1) lookup by index, modification by index, and insertion and removal // operations at the end. Being a persistent variant of the data structure, it // is immutable, and provides O(1) operations to create modified versions of the // vector that shares the underlying data structure, making it suitable for // concurrent access. The empty value is a valid empty vector. type Vector interface { json.Marshaler // Len returns the length of the vector. Len() int // Index returns the i-th element of the vector, if it exists. The second // return value indicates whether the element exists. Index(i int) (interface{}, bool) // Assoc returns an almost identical Vector, with the i-th element // replaced. If the index is smaller than 0 or greater than the length of // the vector, it returns nil. If the index is equal to the size of the // vector, it is equivalent to Cons. Assoc(i int, val interface{}) Vector // Cons returns an almost identical Vector, with an additional element // appended to the end. Cons(val interface{}) Vector // Pop returns an almost identical Vector, with the last element removed. It // returns nil if the vector is already empty. Pop() Vector // SubVector returns a subvector containing the elements from i up to but // not including j. SubVector(i, j int) Vector // Iterator returns an iterator over the vector. Iterator() Iterator } // Iterator is an iterator over vector elements. It can be used like this: // // for it := v.Iterator(); it.HasElem(); it.Next() { // elem := it.Elem() // // do something with elem... // } type Iterator interface { // Elem returns the element at the current position. Elem() interface{} // HasElem returns whether the iterator is pointing to an element. HasElem() bool // Next moves the iterator to the next position. Next() } type vector struct { count int // height of the tree structure, defined to be 0 when root is a leaf. height uint root node tail []interface{} } // Empty is an empty Vector. var Empty Vector = &vector{} // node is a node in the vector tree. It is always of the size nodeSize. type node *[nodeSize]interface{} func () node { return node(&[nodeSize]interface{}{}) } func ( node) node { := * return node(&) } func ( []interface{}) node { var [nodeSize]interface{} copy([:], ) return & } // Count returns the number of elements in a Vector. func ( *vector) () int { return .count } // treeSize returns the number of elements stored in the tree (as opposed to the // tail). func ( *vector) () int { if .count < tailMaxLen { return 0 } return ((.count - 1) >> chunkBits) << chunkBits } func ( *vector) ( int) (interface{}, bool) { if < 0 || >= .count { return nil, false } // The following is very similar to sliceFor, but is implemented separately // to avoid unncessary copying. if >= .treeSize() { return .tail[&chunkMask], true } := .root for := .height * chunkBits; > 0; -= chunkBits { = [(>>)&chunkMask].(node) } return [&chunkMask], true } // sliceFor returns the slice where the i-th element is stored. The index must // be in bound. func ( *vector) ( int) []interface{} { if >= .treeSize() { return .tail } := .root for := .height * chunkBits; > 0; -= chunkBits { = [(>>)&chunkMask].(node) } return [:] } func ( *vector) ( int, interface{}) Vector { if < 0 || > .count { return nil } else if == .count { return .Cons() } if >= .treeSize() { := append([]interface{}(nil), .tail...) [&chunkMask] = return &vector{.count, .height, .root, } } return &vector{.count, .height, doAssoc(.height, .root, , ), .tail} } // doAssoc returns an almost identical tree, with the i-th element replaced by // val. func ( uint, node, int, interface{}) node { := clone() if == 0 { [&chunkMask] = } else { := ( >> ( * chunkBits)) & chunkMask [] = (-1, [].(node), , ) } return } func ( *vector) ( interface{}) Vector { // Room in tail? if .count-.treeSize() < tailMaxLen { := make([]interface{}, len(.tail)+1) copy(, .tail) [len(.tail)] = return &vector{.count + 1, .height, .root, } } // Full tail; push into tree. := nodeFromSlice(.tail) := .height var node // Overflow root? if (.count >> chunkBits) > (1 << (.height * chunkBits)) { = newNode() [0] = .root [1] = newPath(.height, ) ++ } else { = .pushTail(.height, .root, ) } return &vector{.count + 1, , , []interface{}{}} } // pushTail returns a tree with tail appended. func ( *vector) ( uint, node, node) node { if == 0 { return } := ((.count - 1) >> ( * chunkBits)) & chunkMask := clone() := [] if == nil { [] = newPath(-1, ) } else { [] = .(-1, .(node), ) } return } // newPath creates a left-branching tree of specified height and leaf. func ( uint, node) node { if == 0 { return } := newNode() [0] = (-1, ) return } func ( *vector) () Vector { switch .count { case 0: return nil case 1: return Empty } if .count-.treeSize() > 1 { := make([]interface{}, len(.tail)-1) copy(, .tail) return &vector{.count - 1, .height, .root, } } := .sliceFor(.count - 2) := .popTail(.height, .root) := .height if .height > 0 && [1] == nil { = [0].(node) -- } return &vector{.count - 1, , , } } // popTail returns a new tree with the last leaf removed. func ( *vector) ( uint, node) node { := ((.count - 2) >> ( * chunkBits)) & chunkMask if > 1 { := .(-1, [].(node)) if == nil && == 0 { return nil } := clone() if == nil { // This is needed since `m[idx] = newChild` would store an // interface{} with a non-nil type part, which is non-nil [] = nil } else { [] = } return } else if == 0 { return nil } else { := clone() [] = nil return } } func ( *vector) (, int) Vector { if < 0 || > || > .count { return nil } return &subVector{, , } } func ( *vector) () Iterator { return newIterator() } func ( *vector) () ([]byte, error) { return marshalJSON(.Iterator()) } type subVector struct { v *vector begin int end int } func ( *subVector) () int { return .end - .begin } func ( *subVector) ( int) (interface{}, bool) { if < 0 || .begin+ >= .end { return nil, false } return .v.Index(.begin + ) } func ( *subVector) ( int, interface{}) Vector { if < 0 || .begin+ > .end { return nil } else if .begin+ == .end { return .Cons() } return .v.Assoc(.begin+, ).SubVector(.begin, .end) } func ( *subVector) ( interface{}) Vector { return .v.Assoc(.end, ).SubVector(.begin, .end+1) } func ( *subVector) () Vector { switch .Len() { case 0: return nil case 1: return Empty default: return .v.SubVector(.begin, .end-1) } } func ( *subVector) (, int) Vector { return .v.SubVector(.begin+, .begin+) } func ( *subVector) () Iterator { return newIteratorWithRange(.v, .begin, .end) } func ( *subVector) () ([]byte, error) { return marshalJSON(.Iterator()) } type iterator struct { v *vector treeSize int index int end int path []pathEntry } type pathEntry struct { node node index int } func ( pathEntry) () interface{} { return .node[.index] } func ( *vector) *iterator { return newIteratorWithRange(, 0, .Len()) } func ( *vector, , int) *iterator { := &iterator{, .treeSize(), , , nil} if .index >= .treeSize { return } // Find the node for begin, remembering all nodes along the path. := .root for := .height * chunkBits; > 0; -= chunkBits { := ( >> ) & chunkMask .path = append(.path, pathEntry{, }) = [].(node) } .path = append(.path, pathEntry{, & chunkMask}) return } func ( *iterator) () interface{} { if .index >= .treeSize { return .v.tail[.index-.treeSize] } return .path[len(.path)-1].current() } func ( *iterator) () bool { return .index < .end } func ( *iterator) () { if .index+1 >= .treeSize { // Next element is in tail. Just increment the index. .index++ return } // Find the deepest level that can be advanced. var int for = len(.path) - 1; >= 0; -- { := .path[] if .index+1 < len(.node) { break } } if == -1 { panic("cannot advance; vector iterator bug") } // Advance on this node, and re-populate all deeper levels. .path[].index++ for ++; < len(.path); ++ { .path[] = pathEntry{.path[-1].current().(node), 0} } .index++ } type marshalError struct { index int cause error } func ( *marshalError) () string { return fmt.Sprintf("element %d: %s", .index, .cause) } func ( Iterator) ([]byte, error) { var bytes.Buffer .WriteByte('[') := 0 for ; .HasElem(); .Next() { if > 0 { .WriteByte(',') } , := json.Marshal(.Elem()) if != nil { return nil, &marshalError{, } } .Write() ++ } .WriteByte(']') return .Bytes(), nil }