# Changing a "constant" type and triggering recompilation

**URL:** https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844
**Category:** Performance
**Created:** [May 28, 2024, 2:32pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844 "2024-05-28T14:32:39Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![RGonTheNoble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rgonthenoble/32/209422_2.png) [@RGonTheNoble](https://discourse.julialang.org/u/RGonTheNoble)
#### Post date: [May 28, 2024, 2:32pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844/1 "2024-05-28T14:32:39Z")

</div>

I’m writing a calculation engine that is going to run as a service. This is for an industrial system, where data sources (tags) have units. Because many of these units have offsests (Fahrenheit, PSI-gauge) I can’t use DynamicQuantities.jl, instead, I’m stuck using Unitful.jl. In order to have type-stability, I need a strongly-typed mixed container like a NamedTuple as a constant.

```julia
const TAG_UNITS = (
        tag1 = u"mcfd",
        tag2 = u"ozp",
        tag3 = u"°F"
)

```

These units are present in a CSV file, so I can even have the constant loaded from the information in the CSV file. So far so good. However, the units of these tags may (rarely) change. It would be nice if I could somehow change that constant and recompile all the code that uses it without having to restart the Julia process.

I’m currently considering using a dynamic module pattern. Something like

```julia
function unit_conversions(modulefile::String)
    m = Module(:UnitConversions)
    Base.include(m, modulefile)
    return m
end

const UNIT_CONVERSIONS = Ref(unit_conversions("unit_conversions.jl"))

function update_units()
    UNIT_CONVERSIONS[] = unit_conversions("unit_conversions.jl")
end

```

The actual module will contain the constant as well as all tag unit conversions operations. So all unit conversions operations would use a call like

```julia
si_tag_dict = UNIT_CONVERSIONS[].to_si_units(raw_tag_dict)

```

I know that this can result in “world-age” issues if `UNIT_CONVERSIONS[]` changes inside a function that references it, so I’m either going to have Python call this function from within a FastAPI app, or have it called as an explicit endpoint in a REST API in an HTTP.jl app.

I feel like this is a bit kludgy, but it feels like the least kludgy way to do this. I’m wondering if this option is sane, and whether or not there’s a more canonical way to have this behaviour.

---

<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: [May 28, 2024, 2:59pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844/2 "2024-05-28T14:59:13Z")

</div>

I mean… don’t use a constant if it’s not constant? Sure, that will incur type instabilities, but _so will calling out to python/HTTP/whatever._ Not only will that have type instabilities on the Julia side, now you have two problems — you gotta maintain two systems.

It just seems you are digging a deeper and deeper rabbit hole here.

---

<div class="post-metadata">

### Author: ![RGonTheNoble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rgonthenoble/32/209422_2.png) [@RGonTheNoble](https://discourse.julialang.org/u/RGonTheNoble)
#### Post date: [May 28, 2024, 3:56pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844/3 "2024-05-28T15:56:01Z")

</div>

The problem is that it _ **usually is constant** _, and that information is required repeatedly at a pretty low level but it might change once or twice in a year. The HTTP/Python callout happens at a very high level so I’m not worried about that. The way your response is framed isn’t very helpful. I guess the more canonical way might be is to use the function barrier technique and include the units object as a high-level argument in a function that only gets called once? Is that what you’re suggesting?

---

<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: [May 28, 2024, 4:06pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844/4 "2024-05-28T16:06:10Z")

</div>

My point is more that there’s no free lunch here. If you want it to be able to change types, then that’s a type instability no matter how you cut it. The program needs to be able to dynamically change its behavior. Type instabilities are one way to handle that dynamic change — and it’s a _feature_ built into Julia itself.

You could alternatively use a function definition for this — something as simple as `units() = (tag1 = u"mcfd",tag2 = u"ozp", tag3 = u"°F")` — but yes, now you’ll need to handle that dynamicism with `@invokelatest`. Which, really, isn’t all that different from just doing the straightforward thing with a function barrier.

Or you could encode your units in a way that doesn’t use the type system. Yes, that means giving up on Unitful, but it depends on how much Unitful is “paying you back” in terms of the functionality you gain.

---

<div class="post-metadata">

### Author: ![RGonTheNoble](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rgonthenoble/32/209422_2.png) [@RGonTheNoble](https://discourse.julialang.org/u/RGonTheNoble)
#### Post date: [May 28, 2024, 5:26pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844/5 "2024-05-28T17:26:36Z")

</div>

I’m fully aware that there’s a type instability any way you cut it. What I’m trying to do is _ **minimize the performance impact** _ of this necessary type instability. For example, lets say I have something like this

```julia
TAG_LIST = ("tag1", "tag2", "tag3")

function units_from_csv(tag_csv_file)
    #... (reads csv file into tag_dict with tags as keys and string units as values)
    tag_pair(tag::String) = Symbol(tag)=>uparse(tag_dict[tag])
    unit_pairs = map( tag_pair, for tag in TAG_LIST)
    return (; unit_pairs...)
end
    
TAG_UNITS = units_from_csv("tag_units.csv")

function update_units_from_csv(tag_csv_file)
    global TAG_UNITS
    TAG_UNITS = units_from_csv("tag_units.csv")
end

function convert_units(tag_dict, units)
   #... (loop through the units in "units" and produce si_tag_dict::Dict{String,Float64})
   return si_tag_dict
end

convert_units(tag_dict) = convert_units(tag_dict, TAG_UNITS)

```

With this, I’m guessing that if I call `convert_units(tag_dict)` it will use dynamic dispatch once, but since we’re calling on a constant value, it won’t change while the function is running, so everything inside `convert_units(tag_dict, TAG_UNITS)` will be type-stable, so I only pay the price of type-instability once. Correct?

---

<div class="post-metadata">

### Author: ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)
#### Post date: [May 28, 2024, 9:59pm UTC](https://discourse.julialang.org/t/changing-a-constant-type-and-triggering-recompilation/114844/6 "2024-05-28T21:59:25Z")

</div>

I don’t know the structure of your program, but I assume it has a main loop.

What you could do is

1. make your global constant into a function which returns the current units.

2. wrap the main loop in an outer function which checks for an updated value for the units, and `@eval`s a new version of the global constant function that contains the new values. It would then call `invokelatest(main_loop)`.

3. periodically break out of the main loop to go back up to the wrapper function.
