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