# How do I create an anonymous function from external variables?

I am trying create a anomymous function with external variables

``````idx = 3; #External Variable
f = x -> x[idx];
``````

As an example

``````idx = 2 #change the value
x = [2,3,5]
f(x)
3
``````

I would expect the output to be like

``````f = x -> x[3]
f(x)
5
``````

Any suggestions for decoupling the external variable?

`f = x -> x[eval(:idx)];`

@jling Thank you so much for your help.

I get this error

``````idx = nothing
f(x)
ArgumentError: `nothing` should not be printed; use `show`, `repr`, or custom output instead.
``````

what behavior do you expect to get, this is basically:

``````julia> x = [2,3,5]
3-element Array{Int64,1}:
2
3
5

julia> x[nothing]
``````

No thatâ€™s not going to make any difference.

Itâ€™s not super clear what you want. Your function is referencing two â€śexternal variablesâ€ť (global variables) `x` and `idx`. Are you just saying that you want to make one of them refering to the global variable `x` while the other one doesnâ€™t refer to the global variable `idx` anymore?

(edit: sorry, I somehow thought `x` is a global variable and not the argument, anyway, apart from the mentioning of `x` above, everything else are still correct so Iâ€™ll just leave it as isâ€¦)

In that case, the solution should come out on itâ€™s own. You just need to make `idx` not be the global variable anymore, i.e. you need to make it a local variable. The way to introduce a local scope is `let` so you basically need

``````f = let idx=idx
x -> x[idx]
end
``````

Of course if you donâ€™t need `idx` to be a variable, you can splice that into the code directly, like `@eval x->x[\$idx]` but thatâ€™s really an overkill.

1 Like

what do you mean?

``````julia> f = x -> x[eval(:idx)];

julia> idx = 2
2

julia> x = [2,3,5]
3-element Array{Int64,1}:
2
3
5

julia> f(x)
3

julia> idx = 3
3

julia> f(x)
5
``````

and his function is NOT referring to 2 global variable because thatâ€™s an anonymous function

I believe you are showing the exact result that was not expected.
What I mean is that your function behaves identically with the original one.

``````julia> f = x -> x[idx]
#3 (generic function with 1 method)

julia> idx = 2
2

julia> x = [2,3,5]
3-element Array{Int64,1}:
2
3
5

julia> f(x)
3

julia> idx = 3
3

julia> f(x)
5
``````

Yeah, see my edit above. However, it has nothing to do with the fact that itâ€™s an anonymous function. Itâ€™s exactly the same for `f(x) = x[idx]`, which is not anonymous. I just missed the `x->` part, i.e. that `x` is the argument, which IS the reason why itâ€™s only refering to 1 global variable and not 2.

ah, my mistake, I thought he was trying to get that result. Sorry for the confusion.

If the question was to get that result for a function constructed in a local scope, then yes, what you had is a valid answer. Itâ€™s not a good answer though and should be discouraged like any unnecessary use of `eval`. The correct solution is to make sure you resolve your variable to the global one explicitly, i.e. by qualifying with the module itâ€™s in, i.e. `x->x[<M>.idx]`. In this case, the `<M>` is the current module, i.e. `@__MODULE__` so it should be `x->x[(@__MODULE__).idx]` (too lazy to check if the `()` is requiredâ€¦edit: actually Iâ€™m pretty sure it isâ€¦ anywayâ€¦)

edit2: of course using `global` also work. Itâ€™s just dirtier for one-liner, but you can do `x->(global idx; x[idx])`â€¦

2 Likes