# Dynamic immutable type

**URL:** <https://discourse.julialang.org/t/dynamic-immutable-type/127168>\
**Category:** New to Julia\
**Tags:** array\
**Created:** [March 20, 2025, 8:48am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168 "2025-03-20T08:48:26Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Soel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soel/32/214997_2.png) [@Soel](https://discourse.julialang.org/u/Soel)\
**Post date:** [March 20, 2025, 8:48am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/1 "2025-03-20T08:48:27Z")

</div>

Hello Julians,

I’m trying to design a type `MyType` having a certain number of fields amongst which `matrix::AbstractMatrix`. In production `MyType` is intended to have its field `matrix` modified (hundreds times a day)… I’ve encountered some difficulties in building `MyType`’s updaters _resizing_/_reshaping_ `matrix`.  
some constraints:  
 `MyType` should be immutable.  
 `matrix` should be a 2-d array.

#### Questions

1. Is there a way to `resize!(matrix)` (empty, update…)?
2. If not, I thought about building the field `matrix` as a `reshape`d `view` on another `MyType`’s field/property, say `kern::AbstractVector` for which operations like `resize!` are more “natural” so that genuinely built _updaters_ on `kern` will lead `matrix` (the rehaped `view` of `kern`) reflect those changes. Is there a way to work around with this idea? A better idea? What are some drawbacks regarding performance etc. ? Should I just let `MyType` be a `mutable struct` and move on?

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 20, 2025, 9:19am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/2 "2025-03-20T09:19:42Z")

</div>

A field of a strictly immutable composite type does not need to reference other immutables, and you can make mutation API forward to that field. That’s how many wrappers of mutable arrays work. A mutable composite type would only add the ability to reassign a different matrix to the field, which is not mutation of the matrix and is likely more expensive.

The real problem is that matrices, or rather any array that isn’t a vector, aren’t straightforwardly resizable. Some examples:

- `push!`-ing 1 element to a MxN matrix where N != 1 can’t result in a matrix
- `resize!`-ing an MxN matrix to P elements isn’t guaranteed to result in a matrix
- `resize!`-ing an MxN matrix to a PxQ matrix has no unique result and would need to copy around most of the elements in general

A matrix type that supports more resizing is in `ElasticArrays.jl`, but that only supports resizing along the last dimension to avoid those issues.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [March 20, 2025, 9:20am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/3 "2025-03-20T09:20:03Z")

</div>

Do you have a bound on the maximum size of the matrix?

---

<div class="post-metadata">

**Author:** ![Soel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soel/32/214997_2.png) [@Soel](https://discourse.julialang.org/u/Soel)\
**Post date:** [March 20, 2025, 9:26am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/4 "2025-03-20T09:26:47Z")

</div>

Thank you for your reply.  
Please, precize what you mean by “…and you can make mutation API forward to that field.” is there a way to make a specific field mutable?  
By the way, you say that `view`ing another field is not a good idea?

---

<div class="post-metadata">

**Author:** ![Soel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soel/32/214997_2.png) [@Soel](https://discourse.julialang.org/u/Soel)\
**Post date:** [March 20, 2025, 9:29am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/5 "2025-03-20T09:29:04Z")

</div>

No sir, I do not have any limit. It can grow to any size… but in practice the number of columns will unlikely go above 40.  
It’s the number of rows that can go to the thousands…  
Though my _updaters_ are there to ensure that sizes/data are correct.

---

<div class="post-metadata">

**Author:** ![karei](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karei/32/214809_2.png) [@karei](https://discourse.julialang.org/u/karei)\
**Post date:** [March 20, 2025, 10:06am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/6 "2025-03-20T10:06:25Z")

</div>

Yes, but read on. Whenever you create a matrix, the system allocates you a block of memory for storing this matrix. The reason why you can’t `resize!(matrix)` is because there is other data near this piece of memory, and easily expanding this matrix might overwrite important data in the surrounding memory. But shrinking this matrix is possible. So if you know the maximum size of the matrix, you can preallocate a maximum block of memory to store it. The following code gives you the freedom to change the size of the matrix _with 0 cost_:

```julia
using Buffers
buffer1 = MAllocBuffer(100 * 100); # preallocate 100*100 momery
A = alloc!(buffer1, 10, 10) # a 10*10 matrix `A`
# then change the size of `A`.
drop!(buffer, A)
A = alloc!(buffer1, 50, 60)

```

However, according to your description, the change in the size of that array is very dynamic and can get very large. So, preallocation is not a good idea. There are still two ways to do this:

1. create your `MyType` as a mutable struct and reallocate the matrix each time its size changes, this method is best suited to your dynamic size characteristics.
2. use a buffer that automatically expands when you run out of buffers, for example:

```julia
using Buffers
buffer = Buffer(100)
A = alloc!(buffer, 10, 10)
drop!(buffer, A)
A = alloc!(buffer, 100, 100)

```

Note that `alloc!(buffer, 10, 10)` returns a matrix view, which makes matrix A slightly slower to compute than `MAllocBuffer`. It’s best to actually test which method faster.

But I think both methods are definitely faster than the second point you made, which is to create a vector and view it as a matrix and engage the operation.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [March 20, 2025, 10:41am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/7 "2025-03-20T10:41:42Z")

</div>

Some workarounds:

- introduce a wrapper type for `matrix`:

```julia
mutable struct ReplaceableMatrix
    matrix::Matrix{Float64}
end

struct MyType
    some_field::SomeType
    matrix::ReplaceableMatrix
end

```

- make `MyType` mutable with all fields immutable, except for `matrix`:

```julia
mutable struct MyType
    const some_field::SomeType
    matrix::ReplaceableMatrix
end

```

It would be possible to add a `resize!` method for `Array`, however, as some have pointed out, the desired semantics of such a method would not be obvious (what should happen to the existing elements).

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [March 20, 2025, 12:11pm UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/8 "2025-03-20T12:11:13Z")

</div>

My idea was to have a maximal fixed-size matrix and just store integers telling you which submatrix is currently in use

---

<div class="post-metadata">

**Author:** ![Soel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soel/32/214997_2.png) [@Soel](https://discourse.julialang.org/u/Soel)\
**Post date:** [March 20, 2025, 7:09pm UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/9 "2025-03-20T19:09:26Z")

</div>

… **Buffers** , ok thanks. But what I don’t want is to had more dependencies…

---

<div class="post-metadata">

**Author:** ![Soel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soel/32/214997_2.png) [@Soel](https://discourse.julialang.org/u/Soel)\
**Post date:** [March 20, 2025, 7:11pm UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/10 "2025-03-20T19:11:59Z")

</div>

Yes sir, I got you.

---

<div class="post-metadata">

**Author:** ![Soel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/soel/32/214997_2.png) [@Soel](https://discourse.julialang.org/u/Soel)\
**Post date:** [March 20, 2025, 7:19pm UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/11 "2025-03-20T19:19:00Z")

</div>

Haha, `mutable struct ReplaceableMatrix`… was my first idea but thought was too easy… definitely what I’m gonna do!! Thank you!!

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [April 12, 2025, 10:19am UTC](https://discourse.julialang.org/t/dynamic-immutable-type/127168/12 "2025-04-12T10:19:33Z")

</div>

Newly relevant:

> [@\[ANN\]: ZeroDimensionalArrays.jl: zero-dimensional arrays/references/boxes](https://discourse.julialang.org/t/ann-zerodimensionalarrays-jl-zero-dimensional-arrays-references-boxes/128002):
>
> [ZeroDimensionalArrays.jl](https://github.com/JuliaArrays/ZeroDimensionalArrays.jl) is being registered, meaning it has entered the three-day-long wait period. Feel free to suggest breaking changes until the wait period is over! It’s a tiny package, implementing several similar types, each being a zero-dimensional array. The package is a response to the frequent confusion regarding Ref because of the semantic overloading, and the fact that Julia programmers often don’t expect Ref to be an abstract type. It’s meant to replace most/all non-ccall-related…
