# Check recursive immutability

**URL:** <https://discourse.julialang.org/t/check-recursive-immutability/62815>\
**Category:** General Usage\
**Created:** [June 12, 2021, 9:24pm UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815 "2021-06-12T21:24:59Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 12, 2021, 9:24pm UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/1 "2021-06-12T21:24:59Z")

</div>

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

```

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

```julia
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`.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 12, 2021, 9:31pm UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/2 "2021-06-12T21:31:05Z")

</div>

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

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

```

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 12, 2021, 9:35pm UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/3 "2021-06-12T21:35:30Z")

</div>

I think StaticArrays can have mutable interiors.

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

```

Same with `FunctionalCollections.PersistentVector`.

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 13, 2021, 5:07am UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/4 "2021-06-13T05:07:23Z")

</div>

```julia
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,

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

```

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

What is the use case for this?

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 13, 2021, 7:49am UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/5 "2021-06-13T07:49:55Z")

</div>

> [@gustaphe](#):
>
> 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.

Rich Hickey gives a nice talk about this, “The value of values”:

[![](https://global.discourse-cdn.com/julialang/original/3X/a/f/af132fe0e1e23cbc08f42f1f0457d686cf3a8df4.jpeg "The Value of Values with Rich Hickey") ](https://www.youtube.com/watch?v=-6BsiVyC1kM)

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 13, 2021, 8:16am UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/6 "2021-06-13T08:16:30Z")

</div>

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

```julia
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)

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 13, 2021, 8:59am UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/7 "2021-06-13T08:59:34Z")

</div>

> [@gustaphe](#):
>
> 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.

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).

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [June 13, 2021, 9:26am UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/8 "2021-06-13T09:26:43Z")

</div>

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.

How about then

```julia
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

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [June 13, 2021, 9:52am UTC](https://discourse.julialang.org/t/check-recursive-immutability/62815/9 "2021-06-13T09:52:21Z")

</div>

> [@gustaphe](#):
>
> I guess I mean whatever’s the word for “harsh, but neutral”. “Stringent”?

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.
