Skip to content

Commit

Permalink
Merge pull request #5 from lestrrat-go/remove-iter
Browse files Browse the repository at this point in the history
Remove iter
  • Loading branch information
lestrrat authored Oct 16, 2024
2 parents ed6f12c + f28a78a commit 3dbfe38
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 70 deletions.
22 changes: 10 additions & 12 deletions string.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package trie

import (
"iter"
)
type stringTokenizer struct{}

func (stringTokenizer) Tokenize(s string) ([]rune, error) {
var list []rune
for _, r := range s {
list = append(list, r)
}
return list, nil
}

// String returns a Tokenizer that tokenizes a string into individual runes.
func String() Tokenizer[string, rune] {
return TokenizeFunc[string, rune](func(s string) (iter.Seq[rune], error) {
return func(yield func(rune) bool) {
for _, r := range s {
if !yield(r) {
break
}
}
}, nil
})
return stringTokenizer{}
}
83 changes: 25 additions & 58 deletions trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package trie
import (
"cmp"
"fmt"
"iter"
"slices"
"sort"
"strings"
Expand All @@ -16,13 +15,13 @@ import (
// Tokenizer is an object that tokenize a L into individual keys.
// For example, a string tokenizer would split a string into individual runes.
type Tokenizer[L any, K cmp.Ordered] interface {
Tokenize(L) (iter.Seq[K], error)
Tokenize(L) ([]K, error)
}

// TokenizeFunc is a function that implements the Tokenizer interface
type TokenizeFunc[L any, K cmp.Ordered] func(L) (iter.Seq[K], error)
type TokenizeFunc[L any, K cmp.Ordered] func(L) ([]K, error)

func (f TokenizeFunc[L, K]) Tokenize(in L) (iter.Seq[K], error) {
func (f TokenizeFunc[L, K]) Tokenize(in L) ([]K, error) {
return f(in)
}

Expand Down Expand Up @@ -50,8 +49,8 @@ type Node[K cmp.Ordered, V any] interface {
// Value returns the value associated with this node
Value() V

// Children returns the children of this node
Children() iter.Seq[Node[K, V]]
// Children returns the immediate children nodes of this node
Children() []Node[K, V]

// First returns the first child of this node
First() Node[K, V]
Expand All @@ -63,9 +62,9 @@ type Node[K cmp.Ordered, V any] interface {
Parent() Node[K, V]

// Ancestors returns a sequence of ancestors of this node.
// The first element is the current element, progressing all the way
// back to the root element ("")
Ancestors() iter.Seq[Node[K, V]]
// The first element is the root element, progressing all the way
// up to the parent of this node.
Ancestors() []Node[K, V]
}

// New creates a new Trie object.
Expand All @@ -82,17 +81,13 @@ func New[L any, K cmp.Ordered, V any](tokenizer Tokenizer[L, K]) *Trie[L, K, V]
// indicates if the value was found.
func (t *Trie[L, K, V]) Get(key L) (V, bool) {
var zero V
iter, err := t.tokenizer.Tokenize(key)
tokens, err := t.tokenizer.Tokenize(key)
if err != nil {
return zero, false
}

t.mu.RLock()
defer t.mu.RUnlock()
var tokens []K
for x := range iter {
tokens = append(tokens, x)
}
node, ok := getNode(t.root, tokens)
if !ok {
return zero, false
Expand All @@ -101,23 +96,19 @@ func (t *Trie[L, K, V]) Get(key L) (V, bool) {
}

func (t *Trie[L, K, V]) GetNode(key L) (Node[K, V], bool) {
iter, err := t.tokenizer.Tokenize(key)
tokens, err := t.tokenizer.Tokenize(key)
if err != nil {
return nil, false
}

t.mu.RLock()
defer t.mu.RUnlock()
var tokens []K
for x := range iter {
tokens = append(tokens, x)
}
return getNode(t.root, tokens)
}

func getNode[K cmp.Ordered, V any](root Node[K, V], tokens []K) (Node[K, V], bool) {
if len(tokens) > 0 {
for child := range root.Children() {
for _, child := range root.Children() {
if child.Key() == tokens[0] {
// found the current token in the children.
if len(tokens) == 1 {
Expand All @@ -137,14 +128,10 @@ func getNode[K cmp.Ordered, V any](root Node[K, V], tokens []K) (Node[K, V], boo
// Delete removes data associated with `key`. It returns true if the value
// was found and deleted, false otherwise
func (t *Trie[L, K, V]) Delete(key L) bool {
iter, err := t.tokenizer.Tokenize(key)
tokens, err := t.tokenizer.Tokenize(key)
if err != nil {
return false
}
var tokens []K
for x := range iter {
tokens = append(tokens, x)
}

t.mu.Lock()
defer t.mu.Unlock()
Expand Down Expand Up @@ -180,17 +167,12 @@ func delete[K cmp.Ordered, V any](root *node[K, V], tokens []K) bool {

// Put sets `key` to point to data `value`.
func (t *Trie[L, K, V]) Put(key L, value V) error {
iter, err := t.tokenizer.Tokenize(key)
tokens, err := t.tokenizer.Tokenize(key)
if err != nil {
return fmt.Errorf(`failed to tokenize key: %w`, err)
}
node := t.root

var tokens []K
for x := range iter {
tokens = append(tokens, x)
}

node := t.root
t.mu.Lock()
defer t.mu.Unlock()
put[K, V](node, tokens, value)
Expand All @@ -203,7 +185,7 @@ func put[K cmp.Ordered, V any](root Node[K, V], tokens []K, value V) {
}

for _, token := range tokens {
for child := range root.Children() {
for _, child := range root.Children() {
if child.Key() == token {
// found the current token in the children.
// we need to traverse down the trie
Expand Down Expand Up @@ -259,41 +241,26 @@ func (n *node[K, V]) Parent() Node[K, V] {
return n.parent
}

func (n *node[K, V]) Ancestors() iter.Seq[Node[K, V]] {
var ancestors []*node[K, V]
func (n *node[K, V]) Ancestors() []Node[K, V] {
var ancestors []Node[K, V]
for {
n = n.parent
if n == nil {
break
}
ancestors = append(ancestors, n)
}

return func(yield func(Node[K, V]) bool) {
for len(ancestors) > 0 {
cur := ancestors[0]
if cur != nil && !cur.isRoot {
if !yield(cur) {
break
}
}
ancestors = ancestors[1:]
}
}
return ancestors
}

func (n *node[K, V]) Children() iter.Seq[Node[K, V]] {
func (n *node[K, V]) Children() []Node[K, V] {
n.mu.RLock()
children := make([]*node[K, V], len(n.children))
copy(children, n.children)
n.mu.RUnlock()
return func(yield func(Node[K, V]) bool) {
for _, child := range children {
if !yield(child) {
break
}
}
children := make([]Node[K, V], 0, len(n.children))
for _, child := range n.children {
children = append(children, child)
}
n.mu.RUnlock()
return children
}

func (n *node[K, V]) First() Node[K, V] {
Expand Down Expand Up @@ -339,7 +306,7 @@ func Walk[L any, K cmp.Ordered, V any](trie *Trie[L, K, V], v Visitor[K, V]) {
}

func walk[K cmp.Ordered, V any](node Node[K, V], v Visitor[K, V], meta VisitMetadata) {
for child := range node.Children() {
for _, child := range node.Children() {
if !v.Visit(child, meta) {
break
}
Expand Down

0 comments on commit 3dbfe38

Please sign in to comment.