Hi I have a question on defining a function that returns an immutable type.
To be specific, let me define two immutable types:
immutable test1
a::Int64
b::Int64
end
immutable test2
a::Int64
b::Bool
end
For t1 = test1(1,1)
and t2 = test2(1, true)
, I want to change t1.a
and t2.a
from 1
to, say, 2
. But since both test1
and test2
are immutable type, I cannot change the value in the usual way.
So I wrote a function as follows:
using Base.Cartesian
@generated function change_immutable(t::Any, name::Symbol, val::Any)
names = fieldnames(t)
len = length(names)
quote
@ncall $len typeof(t) i->
getindex($names, i) == name ? val : getfield(t, i)
end
end
The first argument takes any (immutable) type, the second argument takes the symbol in the type where the corresponding value needs to be changed to val
, the third argument.
For example, change_immutable(t1, :a, 2)
gives test1(2, 1)
and change_immutable(t2, :a, 2)
gives test2(2, true)
. I know that t1
and t2
haven’t changed, but that is okay and this function does what I want to implement.
But the problem is that change_immutable
function sometimes allocates additional memory. Using the following function:
function memory_test(t)
for i=1:1000
change_immutable(t, :a, i)
end
end
@time memory_test(t1)
returns 0.000013 seconds (4 allocations: 160 bytes)
but
@time memory_test(t2)
returns 0.000067 seconds (1.49 k allocations: 39.047 KiB)
, which allocates additional memory compared to the first case.
Do you know how to construct a function that does the same thing as change_immutable
yet allocates less memory even in test2
immutable type?