From 63de78120c152df81410f2e6c9e828b59a4ddcf5 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 5 Oct 2021 12:46:45 +0200 Subject: [PATCH 1/4] fix #16 --- src/functor.jl | 15 ++++++++------- test/basics.jl | 5 +++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/functor.jl b/src/functor.jl index b502493..e082cd6 100644 --- a/src/functor.jl +++ b/src/functor.jl @@ -192,11 +192,12 @@ julia> fcollect(m, exclude = v -> Functors.isleaf(v)) Bar([1, 2, 3]) ``` """ -function fcollect(x; cache = [], exclude = v -> false) - x in cache && return cache - if !exclude(x) - push!(cache, x) - foreach(y -> fcollect(y; cache = cache, exclude = exclude), children(x)) - end - return cache +function fcollect(x; output = [], cache = Base.IdSet(), exclude = v -> false) + x in cache && return output + if !exclude(x) + push!(cache, x) + push!(output, x) + foreach(y -> fcollect(y; cache=cache, output=output, exclude=exclude), children(x)) + end + return output end diff --git a/test/basics.jl b/test/basics.jl index bc1617b..9d1ce76 100644 --- a/test/basics.jl +++ b/test/basics.jl @@ -84,6 +84,11 @@ end m3 = Foo(m2, m0) m4 = Bar(m3) @test all(fcollect(m4) .=== [m4, m3, m2, m1, m0]) + + m1 = [1, 2, 3] + m2 = [1, 2, 3] + m3 = Foo(m1, m2) + @test all(fcollect(m3) .=== [m3, m1, m2]) end struct FFoo From b0201635e82b2ffb0cda1b48768688b66a0c413e Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 5 Oct 2021 12:46:55 +0200 Subject: [PATCH 2/4] bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index accd6fb..b1bc07e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Functors" uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196" authors = ["Mike J Innes "] -version = "0.2.5" +version = "0.2.6" [compat] julia = "1" From 254dea1bcd1aaf71cc0a87f18e71681b07c0be61 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 5 Oct 2021 14:46:13 +0200 Subject: [PATCH 3/4] Update src/functor.jl --- src/functor.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/functor.jl b/src/functor.jl index e082cd6..312a498 100644 --- a/src/functor.jl +++ b/src/functor.jl @@ -193,6 +193,9 @@ julia> fcollect(m, exclude = v -> Functors.isleaf(v)) ``` """ function fcollect(x; output = [], cache = Base.IdSet(), exclude = v -> false) + # note: we don't have an `OrderedIdSet`, so we use an `IdSet` for the cache + # (to ensure we get exactly 1 copy of each distinct array), and a usual `Vector` + # for the results, to preserve traversal order (important downstream!). x in cache && return output if !exclude(x) push!(cache, x) From c1c242192f14c47fd10e3953fdd22d665841661d Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 5 Oct 2021 15:03:47 +0200 Subject: [PATCH 4/4] document the order --- src/functor.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/functor.jl b/src/functor.jl index e082cd6..07295fb 100644 --- a/src/functor.jl +++ b/src/functor.jl @@ -149,7 +149,8 @@ fmapstructure(f, x; kwargs...) = fmap(f, x; walk = (f, x) -> map(f, children(x)) fcollect(x; exclude = v -> false) Traverse `x` by recursing each child of `x` as defined by [`functor`](@ref) -and collecting the results into a flat array. +and collecting the results into a flat array, ordered by a breadth-first +traversal of `x`, respecting the iteration order of `children` calls. Doesn't recurse inside branches rooted at nodes `v` for which `exclude(v) == true`.