# Initiate a struct without its name but only by its type in local scope

**URL:** <https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875>\
**Category:** General Usage\
**Tags:** question, struct\
**Created:** [November 7, 2022, 12:33pm UTC](https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875 "2022-11-07T12:33:44Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![elakelaiset](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elakelaiset/32/22254_2.png) [@elakelaiset](https://discourse.julialang.org/u/elakelaiset)\
**Post date:** [November 7, 2022, 12:33pm UTC](https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875/1 "2022-11-07T12:33:44Z")

</div>

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

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

```

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [November 7, 2022, 12:58pm UTC](https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875/2 "2022-11-07T12:58:53Z")

</div>

If you just want the functionality, I believe the [Accessors](https://github.com/JuliaObjects/Accessors.jl) package solves the problem. If you want to learn how to do this yourself, I would recommend either trying to do it with a regular function or with a macro, rather than with `Meta.parse` and `eval`.

---

<div class="post-metadata">

**Author:** ![elakelaiset](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elakelaiset/32/22254_2.png) [@elakelaiset](https://discourse.julialang.org/u/elakelaiset)\
**Post date:** [November 7, 2022, 1:11pm UTC](https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875/3 "2022-11-07T13:11:50Z")

</div>

@GunnarFarneback Didn’t know that package. Works like a charm. I will tag your answer as solution, but would be still interested how to solve it with a regular function.

Thank you very much!

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [November 7, 2022, 1:13pm UTC](https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875/4 "2022-11-07T13:13:16Z")

</div>

Try this:

```julia
function cpStructWithChangedField(inStruct, chField::Symbol, newValue)
    # type of struct
    inType = typeof(inStruct)
 
    # field count and names
    fc = fieldcount(inType)
    fn = fieldnames(inType)

    args = (field_name == chField ? newValue : getfield(inStruct, field_name)
            for field_name in fn)
    return inType(args...)
end

```

---

<div class="post-metadata">

**Author:** ![elakelaiset](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elakelaiset/32/22254_2.png) [@elakelaiset](https://discourse.julialang.org/u/elakelaiset)\
**Post date:** [November 7, 2022, 1:17pm UTC](https://discourse.julialang.org/t/initiate-a-struct-without-its-name-but-only-by-its-type-in-local-scope/89875/5 "2022-11-07T13:17:55Z")

</div>

That’s really cool. Didn’t know that you can just initiate a new struct by just calling the variable which stores the intended type. Thank you again for the effort and insights. ~~I will close this.~~ I can’t, but anyways, suggested the last answer as solution.
