# Check recursive immutability

``````struct Foo
val::Vector{Int}
end
``````

How can I check if a type is recursively immutable? I tried

``````function recursively_immutable(type)
!type.mutable && all(recursively_immutable(ft) for ft in fieldtypes(type))
end
``````

but it doesn’t work on vectors, because vectors don’t have any `fieldtypes`.

There may be an existing solution, but while you are rolling your own you can add methods

``````recursive_mutable(::Type{AbstractArray}) = true
recursive_mutable(::Type{StaticArray}) = false
...
``````

I think StaticArrays can have mutable interiors.

``````sa = SVector{3}([[],[2],[3]])
push!(sa[1], 1)
``````

Same with `FunctionalCollections.PersistentVector`.

``````recursive_mutable(::Type{StaticArray{T}}) where {T} = recursive_mutable(T)
``````

Nore that you’ll need to change your base case to work with arbitrary data types. And that this will only work with single type arrays,

``````StaticArray{Any}([
1, "hi", [3]
])
``````

cannot be investigated statically, but would have to be checked by instance.

What is the use case for this?

I like programming with objects that are immutable “all the way down” because they are just values. This function is a predicate to check whether I have one of these types.

To check if an instance is recursively mutable (at least a start of such a function):

``````function recursive_mutable(x::T) where {T}
isstructtype(T) || return ismutable(x)
return any(recursive_mutable, get.(Ref(x), fieldnames(T)))
end

recursive_mutable(x::AbstractArray) = true
recursive_mutable(x::StaticArray) = any(recursive_mutable, x)
``````

This will, for instance, catch `SArray{Tuple{3}}(Any[1, 2, [1, 2]])`, which wouldn’t be possible on type information alone (unless you want to be really harsh, and for instance say that `Any` is a tainted type. If you wish to implement something like that, you may be interested in `ismutabletype(T)` (which I think is more or less a replacement for `T.mutable` in recent versions)

I’m not seeing why that’s harsh? It seems like I’d want to call that object recursively mutable, since it has mutable components (the third element is a mutable array).

I guess I mean whatever’s the word for “harsh, but neutral”. “Stringent”?

Note, for instance, that if `SArray{Any}` is considered recursively mutable, then `SArray{Tuple{3}}(Any[1, 2, 3])` would be too, even though that specific instance would be perfectly immutable.

``````function recursive_mutable(T::Type)
T === Any && return true
ismutabletype(T) && return true
isstructtype(T) && return any(recursive_mutable, fieldtypes(T))
return false
end

recursive_mutable(::Type{SArray{T, S}}) where {T, S} = recursive_mutable(S)
``````

?

Unfortunately, `Any` and `Union` types are considered immutable, so you have to kludge like I’ve done with `Any` AFAICS

Maybe “strict” is what you’re going for?

That code looks good. I guess I could return `missing` for things like `Any` and let the caller decide what to do.