Skip to content

Commit fb7a21c

Browse files
committed
Make NodeChildren a public type
1 parent f3af8dc commit fb7a21c

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

docs/src/node.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ Base.:(==)(::Node{T}, ::Node{T}) where T
1919
## Accessing child nodes
2020

2121
Internally, to store the children, a node simply stores the reference to the first and the last child node, and each child stores the references to the next and previous child.
22-
The `.children` property is implemented simply as a lazy iterator that traverses the linked list.
22+
The `.children` property is implemented simply as a lazy iterator of type [`NodeChildren`](@ref) that traverses the linked list.
2323
As such, some operations, such as determining the number of children a node has with [`length`](@ref Base.length(::NodeChildren)), can have unexpected ``O(n)`` complexity.
2424

2525
```@docs
2626
haschildren
27+
NodeChildren
2728
Base.eltype(::Type{NodeChildren{T}}) where T
2829
Base.length(::NodeChildren)
2930
Base.isempty(::NodeChildren)

src/node.jl

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ underlying fields of the struct should not be accessed directly.
4646
with the value set to `nothing` if there is no such node
4747
- `.parent :: Union{Node{M},Nothing}`: access the parent node of this node, with the value
4848
set to `nothing` if the node does not have a parent
49-
- `.children`: an iterable object that can be used to acces and modify the children of the
50-
node
49+
- `.children`: an iterable object of type [`NodeChildren`](@ref) that can be used to access
50+
and modify the child nodes of this node
5151
5252
The `.children` field is implemented with a wrapper type that implemements the iteration
5353
protocol. However, the exact type information etc. is an implementation detail, and one
@@ -197,9 +197,18 @@ end
197197
# The precise types etc of the iterator of the child nodes is considered to be an
198198
# implementation detail. It should only be constructed by calling the relevant public APIs.
199199
# In practice, the argument to ChildrenIterator is simply the node where the iterator starts
200+
"""
201+
struct NodeChildren
202+
203+
The type of the the `.children` property of a [`Node`](@ref) which acts as an iterator over
204+
the children of a node. This type is mostly considered to be an implementation detail, and
205+
only has the following publicly defined APIs:
206+
207+
* The name of the type `NodeChildren`, so that it could be dispatched on.
208+
* The `.parent :: Node` field that allows the user to access the parent node of the children.
209+
"""
200210
struct NodeChildren{T <: Node}
201211
parent :: T
202-
203212
NodeChildren(parent::T) where {T <: Node} = new{T}(parent)
204213
end
205214
function Base.iterate(children::NodeChildren{T}, state::Union{T,Nothing} = nothing) where {T <: Node}
@@ -208,15 +217,15 @@ function Base.iterate(children::NodeChildren{T}, state::Union{T,Nothing} = nothi
208217
end
209218

210219
"""
211-
eltype(node.children) = Node{M}
220+
eltype(node.children::NodeChildren) = Node{M}
212221
213222
Returns the exact `Node` type of the tree, corresponding to the type of the elements of the
214223
`.children` iterator.
215224
"""
216225
Base.eltype(::Type{NodeChildren{T}}) where T = T
217226

218227
"""
219-
length(node.children) -> Int
228+
length(node.children::NodeChildren) -> Int
220229
221230
Returns the number of children of `node :: Node`.
222231
@@ -235,7 +244,7 @@ function Base.length(children::NodeChildren)
235244
end
236245

237246
"""
238-
first(node.children) -> Node
247+
first(node.children::NodeChildren) -> Node
239248
240249
Returns the first child of the `node :: Node`, or throws an error if the node has no
241250
children.
@@ -248,7 +257,7 @@ function Base.first(children::NodeChildren{T}) where T
248257
end
249258

250259
"""
251-
last(node.children) -> Node
260+
last(node.children::NodeChildren) -> Node
252261
253262
Returns the last child of the `node :: Node`, or throws an error if the node has no
254263
children.
@@ -261,15 +270,15 @@ function Base.last(children::NodeChildren{T}) where T
261270
end
262271

263272
"""
264-
isemtpy(node.children) -> Bool
273+
isemtpy(node.children::NodeChildren) -> Bool
265274
266275
Can be called on the `.children` field of a `node :: Node` to determine whether or not the
267276
node has any child nodes.
268277
"""
269278
Base.isempty(children::NodeChildren) = !haschildren(children.parent)
270279

271280
"""
272-
Base.push!(node.children, child::Node) -> Node
281+
Base.push!(node.children::NodeChildren, child::Node) -> NodeChildren
273282
274283
Adds `child` as the last child node of `node :: Node`. If `child` is part of another tree,
275284
then it is unlinked from that tree first (see [`unlink!`](@ref)). Returns the iterator over
@@ -305,7 +314,7 @@ function Base.push!(::Node, ::Any)
305314
end
306315

307316
"""
308-
Base.pushfirst!(node.children, child::Node) -> Node
317+
Base.pushfirst!(node.children::NodeChildren, child::Node) -> NodeChildren
309318
310319
Adds `child` as the first child node of `node :: Node`. If `child` is part of another tree,
311320
then it is unlinked from that tree first (see [`unlink!`](@ref)). Returns the iterator over

0 commit comments

Comments
 (0)