# Protect Entry of a Struct

**URL:** https://discourse.julialang.org/t/protect-entry-of-a-struct/55795
**Category:** New to Julia
**Created:** [February 22, 2021, 7:15pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795 "2021-02-22T19:15:03Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)
#### Post date: [February 22, 2021, 7:15pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/1 "2021-02-22T19:15:03Z")

</div>

Hello!

Suppose I have this simple example where I use the Parameters package:

```julia
using Parameters

@with_kw struct MyTest
       a = 1
       b = 2*a
 end

```

Note how b is calculated based on a. If I write:

```julia
MyTest(a=4)
MyTest
  a: Int64 4
  b: Int64 8

```

Which is as expected. On the other hand if I write:

```julia
MyTest(b=5)
MyTest
  a: Int64 1
  b: Int64 5

```

In which case I have overwritten b = 2\*a. Now in some instances this can be useful and so on, but my question is then:

**Is it possible to in some way PROTECT a specific entry in a struct? To ensure that it cannot be set explicitly?**

Or atleast output a warning; “WARNING: MyTest.b was set manually.”

Kind regards

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 22, 2021, 7:20pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/2 "2021-02-22T19:20:06Z")

</div>

The `@with_kw` macro just adds convenience constructors that take kwargs. You can always just define them yourself:

```julia
struct MyTest
    a
    b
    MyTest(;a = 1) = new(a, 2*a)
end

```

---

<div class="post-metadata">

### Author: ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)
#### Post date: [February 22, 2021, 7:23pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/3 "2021-02-22T19:23:40Z")

</div>

I really like the @with\_kw approach and personally also like the ability to overwrite, but I would just like to cast a warning if it has been overwritten.

Thanks for showing me that approach though, I just think it might become convulated qutie fast if say I had 5 entries which had to be calculated in my struct.

Kind regards

---

<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: [February 22, 2021, 7:25pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/4 "2021-02-22T19:25:27Z")

</div>

I think this does what you want:

```julia
julia> @with_kw struct MyTest
         a = 1
         b = 2*a
         function MyTest(a,b)
           @assert b == 2*a
           new(a,b)
         end
       end

julia> MyTest(a=1,b=3)
ERROR: AssertionError: b == 2a

julia> MyTest(b=3)
ERROR: AssertionError: b == 2a

julia> MyTest(a=1,b=2)
MyTest
  a: Int64 1
  b: Int64 2

julia> MyTest(b=2)
MyTest
  a: Int64 1
  b: Int64 2

julia> MyTest(a=3)
MyTest
  a: Int64 3
  b: Int64 6

```

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 22, 2021, 7:29pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/5 "2021-02-22T19:29:29Z")

</div>

Looks like Parameters.jl supports putting those `@asserts` directly in the field definition itself — you needn’t create the constructors yourself. I’d guess something like this would do the ticket:

```julia
@with_kw struct MyTest
    a = 1
    b = 2*a
    @assert b == 2a
 end

```

[https://mauro3.github.io/Parameters.jl/stable/manual/#Types-with-default-values-and-keyword-constructors](https://mauro3.github.io/Parameters.jl/stable/manual/#Types-with-default-values-and-keyword-constructors)

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [February 22, 2021, 7:37pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/6 "2021-02-22T19:37:46Z")

</div>

> [@Ahmed\_Salih](#):
>
> Is it possible to in some way PROTECT a specific entry in a struct? To ensure that it cannot be set explicitly?

Just to address the specific wording here even though I know it’s not really what you mean: No. It is fundamentally impossible in julia to strictly enforce constraints on the values of the fields in a struct.

The best one can do is use inner constructors to enforce constraints, but those can be bypassed in various ways. For instance:

```julia
julia> using Parameters

julia> @with_kw struct MyTest{T}
           a::T = 1
           b::T = 2*a
           @assert b == 2a
       end
MyTest

julia> MyTest(a=1, b=1)
ERROR: AssertionError: b == 2a

julia> reinterpret(MyTest{Int}, [1, 1])[1]
MyTest{Int64}
  a: Int64 1
  b: Int64 1

```

A determined user can always find a way to stick an ‘invalid’ entry into a struct (so long as the type is compatible). The best you can do is make it inconvenient to do so and then tell users that if they bypass your constructors, it’s their own fault if things go wrong.

---

<div class="post-metadata">

### Author: ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)
#### Post date: [February 22, 2021, 7:46pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/7 "2021-02-22T19:46:18Z")

</div>

@lmiq @mbauman

Thanks for your code pieces! It is not exactly what I want, but it is atleast a possible route to go.

@Mason

Most users are not going to figure out the reinterpret trick which you did and I was completely oblivious of it also to be honest - so great find!

Regarding the enforcing of constraints, would it be possible to any way write an @assert expression which basically is a warning? So for example if “b” is set externally and not defined through “a”, then it would simply allow it (because it is not possible to disallow as you say), but print a warning saying that the automatic calculation of this parameter was bypassed.

For my use case the exact value of a or b, is not so important it is just whether or not it was overwritten or calculated based on a predefined expression.

Basically something like I mentioned in the first post; “WARNING: MyTest.b was set manually.” But I would want this for multiple variables, imagine if I had also fields c,d,e,f and so forth.

Kind regards

---

<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: [February 22, 2021, 7:49pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/8 "2021-02-22T19:49:30Z")

</div>

In the custom construct you can just remove the assert and add a warning.

```julia
julia> @with_kw struct MyTest
         a = 1
         b = 2*a
         function MyTest(a,b)
           b == 2*a || println("Warning: b ≠ 2a")
           new(a,b)
         end
       end

```

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [February 22, 2021, 7:51pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/9 "2021-02-22T19:51:31Z")

</div>

> [@Ahmed\_Salih](#):
>
> Regarding the enforcing of constraints, would it be possible to any way write an @assert expression which basically is a warning? So for example if “b” is set externally and not defined through “a”, then it would simply allow it (because it is not possible to disallow as you say), but print a warning saying that the automatic calculation of this parameter was bypassed.

No, the `reinterpret` trick (or other tricks) will also allow one to bypass any automatic warning mechanism. If julia had a mechanism to strictly enforce this stuff, a lot of important optimizations would be impossible.

Don’t worry about the points I’m bringing up here though, it’s most likely not relevant for you. Just stick warnings or assertions in your constructors and you’ll be fine. If a user bypasses your constructors, that’s their fault.

---

<div class="post-metadata">

### Author: ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)
#### Post date: [February 22, 2021, 8:11pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/10 "2021-02-22T20:11:40Z")

</div>

@lmiq

Thanks for the suggestions!

@Mason

Unfortunate, but thanks for the clarification. I personally would like this kind of feature, but I see why it might be difficult to implement etc. Thanks for spending time on the question!

Kind regards

---

<div class="post-metadata">

### Author: ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)
#### Post date: [February 22, 2021, 8:25pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/11 "2021-02-22T20:25:47Z")

</div>

> [@Ahmed\_Salih](#):
>
> Unfortunate, but thanks for the clarification. I personally would like this kind of feature, but I see why it might be difficult to implement etc.

My understanding is that the problem is not that it’s difficult to implement, it’s that the very concept is anathema to julia being usable as a high performance language.

We need these sorts of low level escape hatches for various things. But the upside is that it is considered the user of that escape hatches responsibility to make sure anything they do there is valid. So again, this is not really your problem.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [February 22, 2021, 9:32pm UTC](https://discourse.julialang.org/t/protect-entry-of-a-struct/55795/12 "2021-02-22T21:32:51Z")

</div>

> [@lmiq](#):
>
> `println("Warning: b ≠ 2a")`

Just a nitpick: Better to do `@warn "b ≠ 2a"` to hook into all the existing [logging features](https://docs.julialang.org/en/v1/stdlib/Logging/).
