# Variable interpolation

**URL:** <https://discourse.julialang.org/t/variable-interpolation/117769>\
**Category:** New to Julia\
**Tags:** metaprogramming\
**Created:** [August 2, 2024, 4:39pm UTC](https://discourse.julialang.org/t/variable-interpolation/117769 "2024-08-02T16:39:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![geoffD](https://avatars.discourse-cdn.com/v4/letter/g/cdc98d/32.png) [@geoffD](https://discourse.julialang.org/u/geoffD)\
**Post date:** [August 2, 2024, 4:39pm UTC](https://discourse.julialang.org/t/variable-interpolation/117769/1 "2024-08-02T16:39:56Z")

</div>

Hi, everyone. New to Julia and trying to do something like the following:

```julia
v1 = "m" 

function mat()
    return "I am a mat"
end 

```

I would like to be able to issue the following command:  
($v1)at

and get back “I am a mat”

However, my feeble attempt at interpolating with ($) doesn’t seem to fly. Do I need a macro for this?

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [August 2, 2024, 4:43pm UTC](https://discourse.julialang.org/t/variable-interpolation/117769/2 "2024-08-02T16:43:54Z")

</div>

> [@geoffD](#):
>
> I would like to be able to issue the following command:  
> `($v1)at` and get back `"I am a mat"`

You can use `eval(Meta.parse("$(v1)at()"))`, for example.

However, this sounds like a classic [XY problem](https://xyproblem.info/), in which you are reaching for the wrong tool for the job. What are you ultimately trying to accomplish?

In general, you almost _never_ need to pass functions or expressions as strings — Julia has much better ways to deal with functions as variables. See also [How one can evaluate @printf to be returned to a value - #6 by stevengj](https://discourse.julialang.org/t/how-one-can-evaluate-printf-to-be-returned-to-a-value/117669/6)

---

<div class="post-metadata">

**Author:** ![geoffD](https://avatars.discourse-cdn.com/v4/letter/g/cdc98d/32.png) [@geoffD](https://discourse.julialang.org/u/geoffD)\
**Post date:** [August 2, 2024, 5:28pm UTC](https://discourse.julialang.org/t/variable-interpolation/117769/3 "2024-08-02T17:28:16Z")

</div>

Okay, I’ll bite!

This is part of an agents.jl model that moves patients through a hospital emergency department based on completion of a series of four lab tests.

The logic for the lab tests is identical across tests, so I wrote a single function that handles whatever test is passed to it. The metaprogramming comes in when I need to update values specific to that test. So:

```julia
# get a list of test statuses and choose one at random that is incomplete (status is 1 or 2) 
dxStatus = Dict("ct" => patient.ctStatus, "mri" => patient.mriStatus ,"lab" => patient.labStatus, "xray"=>patient.xrayStatus) 

labName = rand(findall(x-> 0 < x < 3 , dxStatus))

if isempty(labName)
	patient.dxComplete == true 
else
     # pass the testname to the test processing function
     processTest(model, patient,labName)
end 

### the function
function processTest(model, patient,labName)
# check to see if there is space in the lab 
 		if count(x->x.$(labName)Status == 2 ,allagents(model)) < model.$(labName)Capacity
# if capacity, send patient to lab by changing status in process and noting start time. 
 			patient.$(labName)Status = 2
 			patient.$(labName)StartTime = abmtime(model)
 	end
end

```

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [August 2, 2024, 8:10pm UTC](https://discourse.julialang.org/t/variable-interpolation/117769/4 "2024-08-02T20:10:59Z")

</div>

In principle, you could use `getfield(x, Symbol(labName * "Status"))` instead of `x.$(labName)Status`.  
Imho, using runtime generated names in this fashion is rarely a good idea. Here, I would change the data representation instead and have `x.Status` hold a dictionary (or some other type that can be indexed) and call it like `x.Status[labName]` – where `labName` is now a symbol, e.g., `:ct` instead of “ct”. This should both be faster and easier to work with than generating fieldnames at runtime.

---

<div class="post-metadata">

**Author:** ![eldee](https://avatars.discourse-cdn.com/v4/letter/e/b5a626/32.png) [@eldee](https://discourse.julialang.org/u/eldee)\
**Post date:** [August 2, 2024, 8:14pm UTC](https://discourse.julialang.org/t/variable-interpolation/117769/5 "2024-08-02T20:14:00Z")

</div>

It looks to me that currently you’re using something like

```julia
mutable struct Patient
    ctStatus::Int
    mriStatus::Int
    labStatus::Int
    xrayStatus::Int

    ctStartTime::Float64
    mriStartTime::Float64
    labStartTime::Float64
    xrayStartTime::Float64

    dxComplete::Bool
end

```

Instead you could (for example) use

```julia
mutable struct PatientLabInfo
    status::Int
    start_time::Float64
end

mutable struct Patient
    labs_info::Dict{String, PatientLabInfo}
    dx_complete::Bool
end

```

and something similar for your `Model` (type of `model`).

(I switched the naming scheme to snake\_case to make the difference between variables and types clearer, as this can occasionally get confusing for me. But this is not too important. The names themselves might also not be ideal (e.g. `PatientLabInfo` refers to the information about a `Patient` some `Lab` might have). Proper naming is hard without complete understanding of the problem you want to model, and also just in general.)

The lab names (relevant for a given `Patient`) are then encoded as the keys in the `labs_info` `Dict`. The equivalent of your code would be

```julia
patient = Patient(
    Dict("ct" => PatientLabInfo(1, 1.23),
         "mri" => PatientLabInfo(4, 0.01),
         "lab" => PatientLabInfo(3, 2.31),
         "xray" => PatientLabInfo(0, 3.21)),
    false
)

lab_name = rand(findall(lab_info -> 0 < lab_info.status < 3, patient.labs_info))
if isempty(lab_name) 
	patient.dx_complete = true # (You wrote ==, but probably mean = ?)   
else
     # pass the testname to the test processing function
     process_test(model, patient, lab_name)
end 

### the function
function process_test(model, patient, lab_name)
    # check to see if there is space in the lab 
    if count(p->p.labs_info[lab_name].status == 2, allagents(model)) < model.labs_info[lab_name].capacity
        # if capacity, send patient to lab by changing status in process and noting start time. 
 		patient.labs_info[lab_name].status = 2
 		patient.labs_info[lab_name].start_time = abmtime(model)
 	end
end

```

By the way, at the moment you check if the `lab_name` `String` is empty (i.e. `""`), which is presumably never the case? Perhaps you mean that no labs for this patient have status 1 or 2. But in this case the code will already have errored by calling `rand` on an empty collection. Instead you should call `isempty` on the result of the `findall`.

In any case, using this approach you don’t need any string interpolation of lab names into variable names. You simply use the lab names directly as indices in a dictionary.

---

<div class="post-metadata">

**Author:** ![geoffD](https://avatars.discourse-cdn.com/v4/letter/g/cdc98d/32.png) [@geoffD](https://discourse.julialang.org/u/geoffD)\
**Post date:** [August 7, 2024, 2:30am UTC](https://discourse.julialang.org/t/variable-interpolation/117769/6 "2024-08-07T02:30:45Z")

</div>

This seems to get it done. Thanks!

```julia

function processTest(model, patient,labName)
	if patient.dxStatus[labName] == 2 
		if (abmtime(model) - patient.dxStartTimes[labName]) > pois_rand(model.dxDurations[labName])
			patient.dxStatus[labName] = 3
			patient.dxEndTimes[labName] = abmtime(model) 
		end
	elseif patient.dxStatus[labName] == 1
		if count(x -> x.dxStatus[labName] == 2 ,allagents(model)) < model.dxCapacities[labName]
			patient.dxStatus[labName] = 2
			patient.dxStartTimes[labName] = abmtime(model)
		else
			nothing ### no lab available
		end
	else
		nothing 
	end
end

```
