Hi together,
i try to define a function which creates a new composite based on a copy of a given composite, but with a single field changed, and without using mutable structs.
I’ve attached a code snipped which tries to solve this with a string and eval, but I’ve realized that it is only valid in global scope. But maybe it helps to understand the intended functionality.
The final string which would be send to eval, defining a new stuct ChangeMe with a different input for its :y field, is as follows:
"out = ChangeMe(inStruct.x, newValue, inStruct.z, inStruct.s)"
So does anybody have suggestions how to solve this problem? Is there a possibility to initiate such a struct without calling its name, so instead of ChangeMe(x,y,z,s) something like initiateStruct(typeOfThatParticularStruct, args...)? The function is supposed to be general applicable, meaning I never know the name of the composite or how many fields it actually has.
Kind regards
Sebastian
Import Test
struct ChangeMe
x::Int64
y::Int64
z::Int64
s::String
end
function cpStructWithChangedField(inStruct, chField::Symbol, newValue)
# type of struct
inType = typeof(inStruct)
# field count and names
fc = fieldcount(inType)
fn = fieldnames(inType)
# create new struct via meta programming
metaString = String[]
push!(metaString,"out = " * string(inType)*"(")
for field in 1:fc
# if chFiled is found, apply new value
if fn[field] == chField
push!(metaString,"newValue")
else
# otherwise old value from original composite
push!(metaString,"inStruct."*string(fn[field]))
end
# add separation symbol in string
if field != fc
push!(metaString,", ")
else
# no separation after last element
push!(metaString,")")
end
end
# combine array of strings to single string
metaString = join(metaString)
# eval >> not working, only GLOBAL scope!
eval(Meta.parse(metaString))
return out
end
# input composite
inp = ChangeMe(1,2,3,"Hello")
# expected composite
exp = ChangeMe(1,99,3,"Hello")
Test.@test cpStructWithChangedField(inp, :y ,99) == exp