Return empty NamedTuple in `@functor` instead of empty Tuple
https://github.com/FluxML/Flux.jl/pull/1862 made me realize that this was inconsistent.
Maybe a test?
Need to think about the ramifications this has on isleaf a bit first, since that checks === (). I think this is more correct, but it's also breaking unless isleaf is changed too.
Latest commit mainly adds some tests for the existing changes. After some thought, not having isleaf check for NamedTuple{{}, Tuple{}} does make some sense. This allows one to distinguish between an "empty" node and a leaf when performing traversals, thus making exclude functions more precise. One could argue nothing or a custom singleton struct might be a better sentinel value for this, but we'd want better downstream testing before trying that approach.
As a bonus, this brings normal @functor in line with @flexiblefunctor, which has been generating a NamedTuple this whole time.
To check I understand right, what this will change is things like this:
julia> using Functors: @functor, functor
julia> functor(nothing)
((), Returns{Nothing}(nothing))
julia> @functor Nothing # struct with no fields
julia> functor(nothing) # this will change to (;), ...
((), var"#7#8"())
That's correct. I don't believe we have any field-less structs in FluxML, and while norm layers (except LayerNorm) can return (;) if they're not affine that is for trainable, not functor.