Skip to content

Commit

Permalink
docs and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
CarloLucibello committed Oct 21, 2024
1 parent 7d60887 commit 6285507
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 10 deletions.
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
[compat]
Compat = "4.16"
ConstructionBase = "1.4"
OrderedCollections = "1.6"
julia = "1.6"

[extras]
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"

[targets]
test = ["Test", "StaticArrays", "Zygote"]
test = ["Test", "OrderedCollections", "StaticArrays", "Zygote"]
11 changes: 8 additions & 3 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ The following types instead are explicitly marked as leaves in Functors.jl:
- `AbstractArray{<:Number}`
- `AbstractString`

## Appropriate Use
This is because in typical application the internals of these are abstracted away and it is not desirable to traverse them.

Typically, since any function `f` is applied to the leaves of the tree, but it is possible for some functions to require dispatching on the specific type of the fields causing some methods to be missed entirely.
## What if I get an error?

Examples of this include element types of arrays which typically have their own mathematical operations defined. Adding a [`@functor`](@ref) to such a type would end up missing methods such as `+(::MyElementType, ::MyElementType)`. Think `RGB` from Colors.jl.
Since by default Funcotrs.jl tries to traverse most types e.g. when using [`fmap`](@ref), it is possible it fails in case the type has not an appropriate constructor. If use experience this issue, you have a few alternatives:
- Mark the type as a leaf using [`@leaf`](@ref)
- Use the `@functor` macro to specify which fields to traverse.
- Define an appropriate constructor for the type.

If you are not able to traverse types in julia Base, please open an issue.
5 changes: 3 additions & 2 deletions src/walks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ function check_lenghts(x, ys...)
end

_map(f, x::Dict, ys...) = Dict(k => f(v, (y[k] for y in ys)...) for (k, v) in x)
_map(f, x::D, ys...) where {D<:AbstractDict} = constructorof(D)(k => f(v, (y[k] for y in ys)...) for (k, v) in x)

_values(x) = x
_values(x::Dict) = values(x)
_values(x::AbstractDict) = values(x)

_keys(x::Dict) = Dict(k => k for k in keys(x))
_keys(x::D) where {D <: AbstractDict} = constructorof(D)(k => k for k in keys(x))
_keys(x::Tuple) = (keys(x)...,)
_keys(x::AbstractArray) = collect(keys(x))
_keys(x::NamedTuple{Ks}) where Ks = NamedTuple{Ks}(Ks)
Expand Down
20 changes: 16 additions & 4 deletions test/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,19 @@ end
@test collect(x) isa Vector{<:Tuple{Complex, Complex}}
end

# @testset "AbstractDict is leaf" begin
# struct DummyDict{K,V} <: AbstractDict{K,V} end
# @test Functors.isleaf(DummyDict{Int,Int}())
# end
@testset "AbstractString is leaf" begin
struct DummyString <: AbstractString
str::String
end
s = DummyString("hello")
@test Functors.isleaf(s)
end

@testset "AbstractDict is functor" begin
od = OrderedDict(1 => 1, 2 => 2)
@test !Functors.isleaf(od)
od2 = fmap(x -> 2x, od)
@test od2 isa OrderedDict
@test od2[1] == 2
@test od2[2] == 4
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using Functors, Test
using Zygote
using LinearAlgebra
using StaticArrays
using OrderedCollections: OrderedDict

@testset "Functors.jl" begin
include("basics.jl")
Expand Down

0 comments on commit 6285507

Please sign in to comment.