# Set struct's parameters using a function whose first argument is for the struct

**URL:** <https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264>\
**Category:** New to Julia\
**Tags:** question, struct\
**Created:** [September 8, 2020, 1:30pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264 "2020-09-08T13:30:39Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [September 8, 2020, 1:30pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/1 "2020-09-08T13:30:39Z")

</div>

Hi, I’m trying to reuse a function to set parameters of a struct.  
For example, I have a function whose the first argument should have type `MyStruct`:

```julia
function set_parameter(mystruct::MyStruct)
    mystruct.a = 1
end

```

And I want to use it to set some parameters of the following struct.

```julia
mutable struct MyStruct
    ???? = set_parameter(????)
    b::Int
end

```

The reason why I’m trying to do this is to reuse the function, which is that I used to do in Python.

Is there any way to resolve this?

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [September 8, 2020, 1:53pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/2 "2020-09-08T13:53:07Z")

</div>

```julia
mutable struct MyStruct
    a

    function MyStruct(a)
        s = new();
        set_a!(s, a);
        return s
    end
end

set_a!(s :: MyStruct, a) = (s.a = a);

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 8, 2020, 1:57pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/3 "2020-09-08T13:57:40Z")

</div>

Perhaps this?

```julia
mutable struct MyStruct
    a
    b::Int
end
set_parameter(mystruct::MyStruct) = mystruct.a
MyStruct(s :: MyStruct,b :: Int64) = MyStruct(set_parameter(s),b)
s1 = MyStruct(1,2)
s2 = MyStruct(s1,3)

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [September 8, 2020, 2:10pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/4 "2020-09-08T14:10:52Z")

</div>

I do not understand why you are trying to call a method inside a struct definition. Are you trying to use [default struct values](https://github.com/JuliaLang/julia/issues/10146) they are not yet implemented but are to be a feature in the future.

Does [Parameters.jl](https://github.com/mauro3/Parameters.jl) not solve your problems?

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [September 8, 2020, 2:25pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/5 "2020-09-08T14:25:39Z")

</div>

@Henrique_Becker  
Not in this case.  
For example, I wanna solve optimisation problem with initial guess. In this case, I would like to set an initial value of the optimisation problem using function like `initial_guess!` (outside the module).  
Also, I sometimes wanna use a default value as an initial value (that is, being lazy).

To do so, I usually write Python codes like this (sorry for this awful code; I’m typing this via my cellphone, and this may be a wrong code):

```julia
class ABC():
    def __init__ (self):
        self.p = set_initial_value(0.)
        
    def set_initial_value(self, s):
        self.p = s

```

Actually, @hendri54 's solution is what I needed.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [September 8, 2020, 3:18pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/6 "2020-09-08T15:18:20Z")

</div>

That can be done through multiple dispatch:

```julia
mutable struct Foo
    a
    b
end

Foo(b) = Foo(1, b)

```

You now have two constructors, one needs both `a` and `b` and one only `b`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 8, 2020, 4:07pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/7 "2020-09-08T16:07:36Z")

</div>

Nothing against other solutions, but it seems that for what you want the suggestion of Henrique would provide a clearer code:

```julia

julia> using Parameters

julia> @with_kw mutable struct S
           a :: Float64 = 0.
           b :: Float64 = 1.
       end
S

julia> initial_value = S()
S
  a: Float64 0.0
  b: Float64 1.0

julia> initial_value = S(a = 5.)
S
  a: Float64 5.0
  b: Float64 1.0

julia> initial_value = S(a = 5., b = 3.)
S
  a: Float64 5.0
  b: Float64 3.0

julia> initial_value = S(a = initial_value.a)
S
  a: Float64 5.0
  b: Float64 1.0

```

and you could additionally define

```julia
julia> S(s::S) = S((getfield(s,field) for field in fieldnames(S))...)
S

julia> S(initial_value)
S
  a: Float64 5.0
  b: Float64 1.0

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [September 8, 2020, 5:06pm UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/8 "2020-09-08T17:06:45Z")

</div>

What’s best seems to depend on whether or not the `set_parameter` method truly requires a (partially initialized) `MyStruct` as input (as the OP specified the way I understood it). If not, then `Parameters.jl` is certainly the way to go.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [September 9, 2020, 12:53am UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/9 "2020-09-09T00:53:52Z")

</div>

I was just playing a little bit with that problem, and this is a general solution, for any number of parameters. You can set any of the fields “by hand”, and the others will be filled up by the values of the previous input structure:

```julia
struct S
  a
  b
end

function S(s :: S; opt...)
  opt_keys = keys(opt) 
  opt_values = values(opt)
  pars = []
  for field in fieldnames(S)
    if ! (field in opt_keys)
      append!(pars,getfield(s,field))
    else
      append!(pars,opt_values[field])
    end
  end
  return S(pars...)
end

s = S(0,0)

@show s

@show S(s,b=1)

@show S(s,a=1)

@show S(s,a=1,b=1)    

```

Results:

```julia
s = S(0, 0)
S(s, b = 1) = S(0, 1)
S(s, a = 1) = S(1, 0)
S(s, a = 1, b = 1) = S(1, 1)

```

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [September 9, 2020, 2:46am UTC](https://discourse.julialang.org/t/set-structs-parameters-using-a-function-whose-first-argument-is-for-the-struct/46264/10 "2020-09-09T02:46:42Z")

</div>

> [@lmiq](#):
>
> I was just playing a little bit with that problem, and this is a general solution, for any number of parameters.

For a generic solution for changing immutables (and also mutables), I highly recommend [Setfield.jl](https://github.com/jw3126/Setfield.jl). It is useful, especially for nested immutables. You don’t need to understand anything complex for just using it, but if you want to know the idea behind Setfield.jl, this JuliaCon talk is a great introduction:

[![](https://global.discourse-cdn.com/julialang/original/3X/5/4/54ca8141e59ef0c6d6da8d82e4fd6b2e54f91e50.jpeg "JuliaCon 2020 | Changing the immutable | Jan Weidner") ](https://www.youtube.com/watch?v=vkAOYeTpLg0)
