# Maintain backwards compatibility when using \`const\` on a mutable struct field

**URL:** https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965
**Category:** General Usage
**Tags:** question
**Created:** [August 19, 2022, 3:46am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965 "2022-08-19T03:46:28Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [August 19, 2022, 3:46am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/1 "2022-08-19T03:46:28Z")

</div>

I searched, and it doesn’t look like anyone has asked this before, but I would be surprised if I am the first, so I apologize if this question is a dupe and I missed it.

In the newly released Julia v1.8.0, you can annotate a field of a mutable struct with `const` like so:

```julia-repl
julia> mutable struct Smile
           const curvature::Float64
       end

```

In 1.6.7, this is a syntax error:

```julia
julia> mutable struct Smile
           const curvature::Float64
       end
ERROR: syntax: expected assignment after "const"
Stacktrace:
 [1] top-level scope
   @ none:1

```

Is there a way to define `Smile` so that if the version is \< 1.8.0, it is just a `struct`, and if the version is ≥ 1.8.0, it is a `mutable struct` with `const curvature`?

Would it be wise to do so?

* * *

Note that the following fails in 1.6.7:

```julia
julia> if VERSION >= v"1.8.0"
           mutable struct Smile
               const curvature::Float64
           end
       else
           struct Smile
               curvature::Float64
           end
       end
ERROR: syntax: expected assignment after "const"
Stacktrace:
 [1] top-level scope
   @ none:1

```

---

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [August 19, 2022, 3:50am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/2 "2022-08-19T03:50:57Z")

</div>

To give a little more context, users of my package\[1\] are currently used to `Smile` being an (immutable) `struct`, and now I want to give them the option of mutating some (but not all) of the fields of `Smile`. But I also want to maintain compatibility with the LTS branch, with the understanding that the mutation functionality will only be available if you use v1.8.0 or higher.

So, I’m _not_ trying to turn a `mutable struct` into a `mutable struct` with `const` fields, which would be a breaking change (because users of the package may have written code that mutates a field that is now going to become immutable). Rather, I’m trying to change a `struct` into a `mutable struct`.

* * *

1. Me.

---

<div class="post-metadata">

### Author: ![dilumaluthge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dilumaluthge/32/29283_2.png) [@dilumaluthge](https://discourse.julialang.org/u/dilumaluthge)
#### Post date: [August 19, 2022, 3:51am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/3 "2022-08-19T03:51:03Z")

</div>

Maybe try a `@static if`?

---

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [August 19, 2022, 3:52am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/4 "2022-08-19T03:52:29Z")

</div>

1.6.7:

```julia
julia> @static if VERSION >= v"1.8.0"
           mutable struct Smile
               const curvature::Float64
           end
       else
           struct Smile
               curvature::Float64
           end
       end
ERROR: syntax: expected assignment after "const"
Stacktrace:
 [1] top-level scope
   @ none:1

```

---

<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: [August 19, 2022, 3:57am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/5 "2022-08-19T03:57:16Z")

</div>

How about:

```julia
macro _const(expr)
 if VERSION >= v"1.8.0-"
   Expr(:const, esc(expr))
 else
   esc(expr)
 end
end

```

In v1.7:

```julia
julia> mutable struct Foo
         @_const x
       end

```

In v1.8:

```julia
julia> mutable struct Foo
         @_const x
       end

julia> isconst(Foo, :x)
true

```

Edit: sorry, I missed that you want a _struct_ in v1.7 and below, rather than a mutable struct. So the answer here doesn’t quite work, but at least it shows how you can actually generate code with `const` in it only on v1.8.

---

<div class="post-metadata">

### Author: ![dilumaluthge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dilumaluthge/32/29283_2.png) [@dilumaluthge](https://discourse.julialang.org/u/dilumaluthge)
#### Post date: [August 19, 2022, 3:57am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/6 "2022-08-19T03:57:54Z")

</div>

Hmmm.

You could put the 1.6-compatible struct definition in one source code file, and put the 1.8-compatible struct definition in another file. And then your package would have code of the form:

```julia
if VERSION >= v"1.8"
    include("structs-1.8.jl")
else
    include("structs-1.6.jl")
end
```

---

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [August 19, 2022, 4:14am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/7 "2022-08-19T04:14:14Z")

</div>

@rdeits No worries, it’s clear how you could use the same approach on the `mutable` keyword.

@dilumaluthge This is an elegant solution, with the small downside that you have to repeat all the docstrings, inner constructor methods etc. in each file.

I wonder if there’s a way to have everything in the same file, though? I was surprised that the following doesn’t work, since the [documentation says that](https://docs.julialang.org/en/v1/manual/metaprogramming/) you can use a `begin ... end` block with `@eval`:

```julia
if VERSION >= v"1.8.0"
    @eval begin
        mutable struct Smile
           const curvature::Float64
        end
    end
else
    @eval begin
        struct Smile
            curvature::Float64
        end
    end
end

```

This generates the same syntax error in 1.6.7.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [August 19, 2022, 5:25am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/8 "2022-08-19T05:25:53Z")

</div>

> [@maxkapur](#):
>
> This is an elegant solution, with the small downside that you have to repeat all the docstrings, inner constructor methods etc. in each file.

Presumably, each file would only contain the functionality that is different between the versions, and the rest of the code would be in a common, third file.

---

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [August 19, 2022, 5:57am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/9 "2022-08-19T05:57:49Z")

</div>

The struct definition itself has to appear in each file, and therefore so does its docstring and inner constructor methods.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [August 19, 2022, 7:08am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/10 "2022-08-19T07:08:28Z")

</div>

So you really _did_ mean “small” downside 😉

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [August 19, 2022, 7:14am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/11 "2022-08-19T07:14:13Z")

</div>

The docstring doesn’t need to appear in each file, as you may add it to the struct name instead of the definition. As an example:

```julia
julia> begin
       """
           A
       Struct `A`, wraps an `Int`
       """
       A

       struct A
           x :: Int
       end
       end

help?> A
search: A Any any all abs ARGS ans axes atan asin asec any! all! acsc acot acos abs2 Array atanh atand asinh asind asech asecd ascii angle acsch acscd acoth

  A

  Struct A, wraps an Int

julia> A(2)
A(2)

```

Regarding the inner constructors, if these are identical across versions, perhaps you’ll need a third file that you include within each struct definition 😛

---

<div class="post-metadata">

### Author: ![maxkapur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maxkapur/32/21208_2.png) [@maxkapur](https://discourse.julialang.org/u/maxkapur)
#### Post date: [August 19, 2022, 7:22am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/12 "2022-08-19T07:22:01Z")

</div>

Haha, I’m a bit of a DRY maximalist (refer to first name)

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [January 12, 2023, 5:43am UTC](https://discourse.julialang.org/t/maintain-backwards-compatibility-when-using-const-on-a-mutable-struct-field/85965/13 "2023-01-12T05:43:42Z")

</div>

Unfortunately, even this doesn’t seem to work completely, e.g in [this PR](https://github.com/JuliaApproximation/ApproxFunBase.jl/actions/runs/3899360561/jobs/6658956746), where tests pass on v1.6, but the coverage run fails with the same error. Is there a way to instruct the coverage action to ignore certain files on specific versions?
