Skip to content

Commit 940195a

Browse files
authored
Merge pull request JuliaCollections#99 from ExpandingMan/em/overhaul1
a few more improvements
2 parents 5d3c880 + bd09272 commit 940195a

21 files changed

+415
-364
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "AbstractTrees"
22
uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
3-
version = "0.3.5"
3+
version = "0.4.0"
44
authors = ["Keno Fischer <[email protected]>"]
55

66
[deps]

README.md

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,68 @@
22

33
[![Build Status](https://github.com/JuliaCollections/AbstractTrees.jl/actions/workflows/CI.yml/badge.svg)](https://github.com/JuliaCollections/AbstractTrees.jl/actions/workflows/CI.yml)
44
[![codecov](https://codecov.io/gh/JuliaCollections/AbstractTrees.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaCollections/AbstractTrees.jl)
5-
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaCollections.github.io/AbstractTrees.jl/stable)
65

7-
This package provides several utilities for working with tree-like data structures.
8-
See the [documentation](https://JuliaCollections.github.io/AbstractTrees.jl/stable)
9-
for details,
10-
and [NEWS.md](NEWS.md) for information about important changes.
6+
[![][docs-stable-img]][docs-stable-url] [![][docs-latest-img]][docs-latest-url]
7+
8+
A package for dealing with generalized tree-like data structures.
9+
10+
## Examples
11+
```julia
12+
julia> t = [[1,2], [3,4]]; # AbstractArray and AbstractDict are trees
13+
14+
julia> children(t)
15+
2-element Vector{Vector{Int64}}:
16+
[1, 2]
17+
[3, 4]
18+
19+
julia> getdescendant(t, (2,1))
20+
3
21+
22+
julia> collect(PreOrderDFS(t)) # iterate from root to leaves
23+
7-element Vector{Any}:
24+
[[1, 2], [3, 4]]
25+
[1, 2]
26+
1
27+
2
28+
[3, 4]
29+
3
30+
4
31+
32+
julia> collect(PostOrderDFS(t)) # iterate from leaves to root
33+
7-element Vector{Any}:
34+
1
35+
2
36+
[1, 2]
37+
3
38+
4
39+
[3, 4]
40+
[[1, 2], [3, 4]]
41+
42+
julia> collect(Leaves(t)) # iterate over leaves
43+
4-element Vector{Int64}:
44+
1
45+
2
46+
3
47+
4
48+
49+
julia> struct FloatTree # make your own trees
50+
x::Float64
51+
children::Vector{FloatTree}
52+
end;
53+
54+
julia> AbstractTrees.children(t::FloatTree) = t.children;
55+
56+
julia> AbstractTrees.nodevalue(t::FloatTree) = t.x;
57+
58+
julia> print_tree(FloatTree(NaN, [FloatTree(Inf, []), FloatTree(-Inf, [])]))
59+
NaN
60+
├─ Inf
61+
└─ -Inf
62+
```
63+
64+
[docs-latest-img]: https://img.shields.io/badge/docs-latest-blue.svg
65+
[docs-latest-url]: https://JuliaCollections.github.io/AbstractTrees.jl/dev
66+
67+
[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg
68+
[docs-stable-url]: https://JuliaCollections.github.io/AbstractTrees.jl/stable
69+

docs/src/faq.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ several major obstacles
7979
All of this means that you are unlikely to get type-stable code from AbstractTrees.jl without some
8080
effort.
8181

82-
The simplest way around this is to define the `eltype` of tree iterators
82+
The simplest way around this is to define the `NodeType` trait and `nodetype` (analogous to
83+
`Base.IteratorEltype` and `eltype`):
8384
```julia
84-
Base.IteratorEltype(::Type{<:TreeIterator{ExampleNode}}) = Base.HasEltype()
85-
Base.eltype(::Type{<:TreeIterator{ExampleNode}}) = ExampleNode
85+
AbstractTrees.NodeType(::Type{<:ExampleNode}) = HasNodeType()
86+
AbstractTrees.nodetype(::Type{<:ExampleNode}) = ExampleNode
8687
```
8788
which is equivalent to asserting that all nodes of a tree are of the same type. Performance
8889
critical code must ensure that it is possible to construct such a tree, which may not be trivial.

docs/src/index.md

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ prevsibling
3535
childrentype
3636
childtype
3737
childstatetype
38-
siblings
3938
```
4039

4140
!!! note
@@ -81,6 +80,38 @@ The default value of `ChildIndexing` is `NonIndexedChildren`.
8180
Types with the `IndexedChildren` trait *must* return an indexable object from `children` (i.e.
8281
`children(node)[idx]` must be valid for positive integers `idx`).
8382

83+
#### `NodeType`
84+
```@docs
85+
NodeType
86+
NodeTypeUnknown
87+
HasNodeType
88+
```
89+
90+
Providing the `HasNodeType` trait will guarantee that all nodes connected to the node must be of the
91+
type returned by [`nodetype`](@ref).
92+
93+
An important use case of this trait is to guarantee the return types of a `TreeIterator`. Tree
94+
nodes with `NodeTypeUnknown` cannot have type-stable iteration over the entire tree.
95+
96+
For example
97+
```julia
98+
struct ExampleNode
99+
x::Int
100+
children::Vector{ExampleNode}
101+
end
102+
103+
AbstractTrees.nodevalue(x::ExampleNode) = x.x
104+
AbstractTrees.children(x::ExampleNode) = x.children
105+
106+
AbstractTrees.NodeType(::Type{<:ExampleNode}) = HasNodeType()
107+
AbstractTrees.nodetype(::Type{<:ExampleNode}) = ExampleNode
108+
```
109+
In this example, iteration over a tree of `ExampleNode`s is type-stable with `eltype`
110+
`ExampleNode`.
111+
112+
Providing the `nodetype(::Type)` method is preferable to defining `nodetype(::ExampleNode)` because
113+
it ensures that `nodetype` can be involved at compile time even if values are not known.
114+
84115

85116
## The Indexed Tree Interface
86117
The abstract tree interface assumes that all information about the descendants of a node is
@@ -114,9 +145,25 @@ prevsiblingindex
114145
rootindex
115146
```
116147

148+
## Additional Functions
149+
```@docs
150+
getdescendant
151+
nodevalues
152+
ischild
153+
isroot
154+
intree
155+
isdescendant
156+
treebreadth
157+
treeheight
158+
descendleft
159+
getroot
160+
```
161+
117162
## Example Implementations
118163
- All objects in base which define the abstract trees interface are defined in
119164
[`builtins.jl`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/src/builtins.jl).
120-
- [`IDTree`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/idtree.jl)
121-
- [`OneNode`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/onenode.jl)
122-
- [`OneTree`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/onetree.jl)
165+
- [`IDTree`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/examples/idtree.jl)
166+
- [`OneNode`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/examples/onenode.jl)
167+
- [`OneTree`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/examples/onetree.jl)
168+
- [`FSNode`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/examples/fstree.jl)
169+
- [`BinaryNode`](https://github.com/JuliaCollections/AbstractTrees.jl/blob/master/test/examples/binarytree.jl)

examples/binarytree_core.jl

Lines changed: 0 additions & 25 deletions
This file was deleted.

examples/binarytree_easy.jl

Lines changed: 0 additions & 44 deletions
This file was deleted.

examples/binarytree_infer.jl

Lines changed: 0 additions & 70 deletions
This file was deleted.

examples/fstree.jl

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/AbstractTrees.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ include("printing.jl")
2424
export ParentLinks, StoredParents, ImplicitParents
2525
export SiblingLinks, StoredSiblings, ImplicitSiblings
2626
export ChildIndexing, IndexedChildren, NonIndexedChildren
27-
export nodevalue, children, parentlinks, siblinglinks, childindexing, childtype, childrentype
27+
export NodeType, HasNodeType, NodeTypeUnknown
28+
export nodetype, nodevalue, nodevalues, children, parentlinks, siblinglinks, childindexing, childtype, childrentype
2829
#extended interface
2930
export nextsibling, prevsibling
3031

@@ -35,7 +36,7 @@ export ischild, isroot, isroot, intree, isdescendant, treesize, treebreadth, tre
3536
export TreeCursor, TrivialCursor, ImplicitCursor, SiblingCursor
3637

3738
#indexing
38-
export childindex, childindices, rootindex, parentindex, nextsiblingindex, prevsiblingindex, IndexNode
39+
export getdescendant, childindices, rootindex, parentindex, nextsiblingindex, prevsiblingindex, IndexNode
3940

4041
# iteration
4142
export TreeIterator, PreOrderDFS, PostOrderDFS, Siblings, Leaves, StatelessBFS, MapNode

src/builtins.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
# Tree API implementations for builtin types
22

33
children(x::AbstractArray) = x
4-
ChildIndexing(::AbstractArray) = IndexedChildren()
4+
5+
children(x::Tuple) = x
56

67
children(x::Expr) = x.args
7-
ChildIndexing(::Expr) = IndexedChildren()
88

99
children(p::Pair) = (p[2],)
10-
ChildIndexing(::Pair) = IndexedChildren()
1110

1211
children(dict::AbstractDict) = pairs(dict)

0 commit comments

Comments
 (0)