Interpolation and expression evaluation

Hi: I tried to use interpolation to construct a name of an existing vector and pick the vector for further processing. However, I couldn’t make it to work. The following is an MWE.

data2=ones(2); data3=zeros(3);

function test1(myv; vec2=data2, vec3=data3)
    a = length(myv)  # either 2 or 3
    ex = Symbol("vec",a) # either vec2 or vec3
    sol = :($(eval(ex))) .+ 10 
    return sol
end

test1(rand(2)) # should return [11.0, 11.0]

I got the error message “ERROR: UndefVarError: vec2 not defined”.

Advice will be appreciated.

maybe it’s related to this: How can I eval a local variable in Julia - Stack Overflow
If I’m reading this correctly that would mean that the eval of ex is taking place in the module scope not the local scope of function test1.

1 Like

Thanks for the pointer. Now I understand why my original code did not work: The eval would reference objects in the global/module scope, and there is no vec2 in the global/module scope. Indeed, if I replace Symbol("vec", a) by Symbol("data", a) then it would grab data2 (which is in global scope) to do the work.

Replacing Symbol("vec", a) by Symbol("data", a) get the job done, but it does not look clean. I thought it would be better if we could pass the dataset into a function as an argument, and work on the passed copy of the dataset in the local scope.

So is it possible to do the following things within a function (local scope), or something to the same effect:

  1. pass a few datasets to the function with numerics in the arguments (such as vec2, vec3),
  2. dynamically determine a value in the function (such as a=length(myv)=2),
  3. using the value in Step 2 to pick the appropriate data from among vec2, vec3, etc.

Thanks in advance.

Something like

a = [ones(2),zeros(3)]
function test1(myv; dict = Dict(length(b)=>b for b in a))
return dict[myv] .+ 10
end

When you learn about eval you think it’s a homoiconic code generator thingy. Which it is, but by design, it is highly limited by this only evaluates in global scope. Generally eval is high level stuff for extending modules after the fact, like putting new methods inside of unexported functions.

My experience is if you think you need eval, consider
Step 1.) The power of Dicts, NamedTuples, and closures and dispatch to pass around and access data.

Step 2.) IF that doesn’t work (and it usually does), figure out how macros works and if you need that kind of power.

Step 3.) Finally by this point you may consider eval but more likely you will just redesign your code so you don’t need to do the thing you wanted to do in the first place.

3 Likes

Yes, I know this is nothing like what you tried to do, but it does the same thing in the end. I just want to suggest figuring out how to do “the same thing in the end” without mucking about with Symbol and eval.

2 Likes

Thanks for the useful advice! The Dicts approach is close to what I need. Thanks again.