What are the differences between nfields
and fieldcount
? Is
nfields(x) == fieldcount(typeof(x))
?
What are the differences between nfields
and fieldcount
? Is
nfields(x) == fieldcount(typeof(x))
?
Where you are working directly with structure of a type itself, fieldcount
is appropriate and has related functions e.g. fieldnames
fieldtypes
. When you need to count of all the fields, including internal fields generally not intended for use outside of programming essential Julia features, nfields
works given a Type or given a typed variable.
nfields(::Type{T}) where {T}
works with many but not all types T
(e.g. Singletons, empty structs).
nfields(x::T) where {T}
works given a realization of type T
fieldcount(::Type{T}) where {T}
works given a type T
fieldcount(x::T) where {T}
throws an error.
Extending Base.fieldcount(x::T) where {T} = fieldcount(T)
and then just using fieldcount
is robust and efficient.
julia> two = 2; half = 1//2;
julia> struct OneField{T}
x::T
end;
julia> onefield = OneField("one")
julia> nfields(two) == nfields(Int) == 0;
julia> nfields(half) == nfields(Rational) == 2;
julia> nfields(onefield) == nfields(OneField) == 1
julia> nfields(Int) == fieldcount(Int) == 0;
julia> nfields(Rational) == fieldcount(Rational);
julia> nfields(OneField) == fieldcount(OneField);
# fieldcount(x) where x is two or half or onefield throws and error
Also see this discussion:
This is incorrect. Look at the example mentioned in the issue @Tamas_Papp linked above:
julia> struct Foo end
julia> nfields(Foo)
21
Another difference is that inference sometimes works only with nfields
. (Maybe that’s because nfields
is a built-in function rather than a generic function?)
julia> f(x) = Val(nfields(x))
f (generic function with 1 method)
julia> g(::T) where {T} = Val(fieldcount(T))
g (generic function with 1 method)
julia> @inferred f((a=1,b=2,c=3))
Val{3}()
julia> @inferred g((a=1,b=2,c=3))
ERROR: return type Val{3} does not match inferred return type Val{_A} where _A
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] top-level scope at REPL[53]:1
Thanks for the additional insight @Tamas_Papp @tkf. I have revised my answer therewith.