 # 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
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