Help me with @eval

Hey all :slight_smile:

Below I wrote a minimal working example of what I’m trying to do. But I can’t get it to work. I’m doing something wrong.

julia> mutable struct Test
           field_1        
           field_2        
           field_3        
       end

julia> function test_run()
           test = Test(0,0,0)
           for field_number in 1:3
               @eval test.$(Symbol(:field_, field_number)) = $field_number
           end
           test
       end
test_run (generic function with 1 method)

julia> test_run()
ERROR: UndefVarError: test not defined
Stacktrace:
 [1] top-level scope
   @ none:1

Eval works in global scope, even when called inside a function or some other local scope. That’s why it cannot see the variable test.

In your example you could just remove the function and just run the loop? In general, avoid using eval in functions.

4 Likes

Is there something that evals code in local/ function scope?

No, this would be fundamentally incompatible with how Julia’s JIT compilation works. In this case you can just use setproperty! though, which should be much more efficient anyways.

4 Likes

You don’t need @eval, you can assign the value to a field with setproprerty!:

julia> mutable struct Test
                  field_1
                  field_2
                  field_3
          end

julia> function test_run()
           test = Test(0,0,0)
           for field_number in 1:3
               setproperty!(test, Symbol(:field_, field_number), field_number)
           end
           test
       end
test_run (generic function with 1 method)

julia> test_run()
Test(1, 2, 3)
4 Likes

Thanks! I learnt a lot :heart_eyes:

1 Like