# Using eval to evaluate a variable inside an expression when string interpolation is not ok

**URL:** <https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356>\
**Category:** General Usage\
**Tags:** arrays, eval, functions\
**Created:** [June 7, 2022, 3:27am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356 "2022-06-07T03:27:37Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mikeliux](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeliux/32/35170_2.png) [@mikeliux](https://discourse.julialang.org/u/mikeliux)\
**Post date:** [June 7, 2022, 3:27am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356/1 "2022-06-07T03:27:37Z")

</div>

I am learning Julia and I am trying to create a function to shuffle an n-dimensional array `X` along a desired dimension. This same strategy will be used later to split an array into 2 subarrays along a desired dimension.

The intended use is as follows:

Command:

```julia
A=[[1,2,3] [4,5,6]]
shuffle_array(A,1)

```

Expected Result (random):

```julia
3×2 Matrix{Int64}:
 2 5
 1 4
 3 6

```

My approach was to build a string, parse it and evaluate it. First, I was not using string interpolation for `X` and I got `UndefVarError: X not defined`. I understand this happens because `X` is defined inside a function and not a global variable. So I wrote `$X`, but this string interpolation writing all the elements of `X` as strings and then parsing them as symbols. In my application `X` will contain thousands of elements.

Question 1: how can I pass `X` into an expression so that it is only evaluated in the line that defines `Xshuffled`?  
Question 2: if you have another strategy that avoids using `eval`, please let me know.

Below is a sample code. The line with `@show` shows the undesired effect of typing `$X`

I am running the code in a jupyter notebook with Julia v1.7.

Thank you in advance.

```julia
using Random
function shuffle_array(X::AbstractArray,shuffle_dim::Int=1)
    """ Shuffle a multidimensional array along desired direction"""
    dims = size(X)
    @show ndims = length(dims)
    m = dims[shuffle_dim]    
    ndims==1 && return X[Random.shuffle(1:m)]    
    if shuffle_dim ==1
        left_part = ""
        middle_part = "$X[Random.shuffle(1:$(m)),"
        right_part = chop(":,"^(ndims-shuffle_dim))*"]"        
    elseif shuffle_dim == ndims
        left_part = "$X[" * (":,"^(shuffle_dim-1))
        middle_part = "Random.shuffle(1:$(m))]" 
        right_part = ""        
    else
        left_part = "$X[" * (":,"^(shuffle_dim-1))
        middle_part = "Random.shuffle(1:$(m))," 
        right_part = chop(":,"^(ndims-shuffle_dim))*"]"
    end
    @show left_part*middle_part*right_part
     Xshuffled = eval(Meta.parse(left_part*middle_part*right_part))
    return Xshuffled
end

```

---

<div class="post-metadata">

**Author:** ![mikeliux](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeliux/32/35170_2.png) [@mikeliux](https://discourse.julialang.org/u/mikeliux)\
**Post date:** [June 7, 2022, 4:54am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356/2 "2022-06-07T04:54:42Z")

</div>

For question 2, I realized that this can be done with the help of a `splat` (`...`) operator. See code below. However, I would like to have an answer for question 1. Maybe it would require a macro?

```julia
function shuffle_array2(X::AbstractArray,shuffle_dim::Int=1)
    """ Shuffle a multidimensional array along desired direction"""
    dims = size(X)
    ndims = length(dims)
    ind = vcat([1:dims[i] for i in 1:shuffle_dim-1],
                [Random.shuffle(1:dims[shuffle_dim])],
                [1:dims[i] for i in shuffle_dim+1:ndims])
    return X[ind...]
end

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 7, 2022, 9:53am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356/3 "2022-06-07T09:53:58Z")

</div>

About question 1, the issue is that you’re interpolating into a string, so it has to convert the array `X` to a substring. There’s really no way around that. You could interpolate `X` without conversion into an `Expr` (what `Meta.parse` turns a string into), and I’m pretty sure no conversion happens when that `Expr` is `eval`-ed into working code.

But you really don’t want to generate code for every input array or run all your code in the global scope. Something like `shuffle_array2` or generating such a reusable function is much more preferable. Only suggestion I could give on that is you could instead index with variable numbers of `:`, which seems to be why you tried generating code in the first place. For example, `x[:,:, 1:3, :]` is equivalent to `x[fill(:, 2)..., 1:3, fill(:, 1)...]`.

---

<div class="post-metadata">

**Author:** ![mikeliux](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikeliux/32/35170_2.png) [@mikeliux](https://discourse.julialang.org/u/mikeliux)\
**Post date:** [June 8, 2022, 12:05am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356/4 "2022-06-08T00:05:22Z")

</div>

Thank you @Benny! I had no idea I could use `fill` like that.  
Concerning question 1, I reached the same conclusion after reading some forums. But maybe it could be done with macros (I am not sure how), because there one can quote and escape a variable.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [June 8, 2022, 1:33am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356/5 "2022-06-08T01:33:50Z")

</div>

Macro can’t generate the code you need for this case because its input expressions are parsed from source code and thus only contain expressions, symbols, and literals. `X` isn’t evaluated as the runtime array yet, so a macro won’t have access to the runtime `size`. Only a method would. If you were working with `StaticArray`s where the `size` is in the type, a generated function could work on the `size`, but a macro still couldn’t.

---

<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:** [June 8, 2022, 5:56am UTC](https://discourse.julialang.org/t/using-eval-to-evaluate-a-variable-inside-an-expression-when-string-interpolation-is-not-ok/82356/6 "2022-06-08T05:56:24Z")

</div>

> [@mikeliux](#):
>
> `A=[[1,2,3] [4,5,6]]`

Note that you can also do `A = [1 4; 2 5; 3 6]` instead of first constructing 1d arrays and concatenating them.

> [@mikeliux](#):
>
> I am trying to create a function to shuffle an n-dimensional array `X` along a desired dimension

You can use

```julia
julia> using Random # for shuffle

julia> mapslices(shuffle, A, dims=1)
3×2 Matrix{Int64}:
 2 5
 3 4
 1 6

```

Metaprogramming (generating code) can be a powerful tool, but it’s also a specialized one that is used rarely in practice — it’s not something I would typically recommend for starting users. See [How to warn new users away from metaprogramming - #22 by stevengj](https://discourse.julialang.org/t/how-to-warn-new-users-away-from-metaprogramming/35022/22)
