Julia allows defining self-referential structs (see Manual > Constructors > Incomplete Initialization). Not that you need them to have a cycle, you can just do:
julia> a = []
Any[]
julia> push!(a, a)
1-element Array{Any,1}:
1-element Array{Any,1}:#= circular reference @-1 =#
In other words, any parametric container that can take Any
as type parameter can contain itself. You can see Julia printing utilities are already prepared to deal with such cases.
In your case, your function has no problem with recursive arrays because your if
does not recurse over AbstractArray
, but it does so for the example of self-referential type found in the manual.
julia> mutable struct SelfReferential
obj::SelfReferential
SelfReferential() = (x = new(); x.obj = x)
end
julia> sr = SelfReferential()
SelfReferential(SelfReferential(#= circular reference @-1 =#))
julia> test = Vector{Bool}(undef,0);
julia> chkFieldNames!(sr, sr, test)
Non-primitive type: SelfReferential
Non-primitive type: SelfReferential
Non-primitive type: SelfReferential
...
Non-primitive type: SelfReferential
Non-primitive type: SelfReferential
Non-primitive type: SelfReferentialERROR: StackOverflowError:
Stacktrace:
[1] poptask(::Base.InvasiveLinkedListSynchronized{Task}) at ./task.jl:704
[2] wait at ./task.jl:712 [inlined]
[3] uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:933
[4] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:1005
[5] unsafe_write at ./io.jl:622 [inlined]
[6] write at ./io.jl:686 [inlined]
[7] print at ./show.jl:210 [inlined]
[8] show_sym(::Base.TTY, ::Symbol; allow_macroname::Bool) at ./show.jl:1086
[9] show_sym at ./show.jl:1085 [inlined]
[10] show_type_name(::Base.TTY, ::Core.TypeName) at ./show.jl:591
[11] show_datatype(::Base.TTY, ::DataType) at ./show.jl:618
[12] show(::Base.TTY, ::Type) at ./show.jl:497
[13] print(::Base.TTY, ::Type{T} where T) at ./strings/io.jl:35
[14] print(::Base.TTY, ::String, ::Type{T} where T, ::Vararg{Any,N} where N) at ./strings/io.jl:46
[15] println(::Base.TTY, ::String, ::Vararg{Any,N} where N) at ./strings/io.jl:73
[16] println(::String, ::Type{T} where T) at ./coreio.jl:4
[17] chkFieldNames!(::SelfReferential, ::SelfReferential, ::Array{Bool,1}, ::Int64) at ./REPL[4]:28
[18] chkFieldNames!(::SelfReferential, ::SelfReferential, ::Array{Bool,1}, ::Int64) at ./REPL[4]:29 (repeats 37315 times)
So, it is good to keep this in mind. With sufficiently exotic types your function will break.