Functors.jl icon indicating copy to clipboard operation
Functors.jl copied to clipboard

Return empty NamedTuple in `@functor` instead of empty Tuple

Open ToucheSir opened this issue 3 years ago • 2 comments

https://github.com/FluxML/Flux.jl/pull/1862 made me realize that this was inconsistent.

ToucheSir avatar Feb 05 '22 18:02 ToucheSir

Maybe a test?

mcabbott avatar Feb 05 '22 18:02 mcabbott

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.

ToucheSir avatar Feb 05 '22 18:02 ToucheSir

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.

ToucheSir avatar Nov 15 '22 01:11 ToucheSir

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"())

mcabbott avatar Nov 15 '22 19:11 mcabbott

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.

ToucheSir avatar Nov 15 '22 23:11 ToucheSir