# VS Code error: Varaible has been assigned but not used

Hello

I am puzzled by an error message in VS code. I have the folloing function below and VS Code is telling me that at line 11, where I compute the likelihood, that VARIABLE HAS BEEN ASSIGNED BUT NOT USED.

The function seems to work fine! It is NOT returning 0.0, it is returning the correct value.

``````function dummyfunc(tile::UInt32, W::Vector{BigFloat})::BigFloat
likelihood = BigFloat(0.0)
T =  T3x3(W)
a = pairs(patchdictionary)
foreach(a) do paire
if tile == paire[1]
p1 = Int(paire[1] & 0x000000ff)
p2 = Int((paire[1] & 0x0000ff00) >> 8)
p3 = Int((paire[1] & 0x00ff0000) >> 16)
p4 = Int((paire[1] & 0xff000000) >> 24)
likelihood = (W[p1] * W[p2] * W[p3] * W[p4]) / T # <--- This is where 'likelihood' is greyed out by VS Code
end
end
return likelihood
end
``````

It seem a bug in the linter for me. Yet, isnÂ´t this clearer?

``````function dummyfunc(tile::UInt32, W::Vector{BigFloat})::BigFloat
likelihood = BigFloat(0.0)
T =  T3x3(W)
for paire in pairs(patchdictionary)
if tile == paire[1]
p1 = Int(paire[1] & 0x000000ff)
p2 = Int((paire[1] & 0x0000ff00) >> 8)
p3 = Int((paire[1] & 0x00ff0000) >> 16)
p4 = Int((paire[1] & 0xff000000) >> 24)
likelihood = (W[p1] * W[p2] * W[p3] * W[p4]) / T # <--- This is where 'likelihood' is greyed out by VS Code
end
end
return likelihood
end
``````
``````help?> foreach
search: foreach

foreach(f, c...) -> Nothing

Call function f on each element of iterable c. For multiple iterable arguments, f is called elementwise, and
iteration stops when any iterator is finished.

foreach should be used instead of map when the results of f are not needed, for example in foreach(println, array).
``````

Therefor it seems to be the right thing to say itâ€™s not used.
Anyways, as we are in a function, the scope of `likelihood` seems not to change, so the value of `likelihood` is changed inside of the anonymous function, e.g. a MWE (VSCode shows the same behaviour):

``````julia> function foo()
a=[1,2,3]
y=0
foreach(a) do x
y=x
end
y
end
foo (generic function with 1 method)

julia> foo()
3
``````

https://docs.julialang.org/en/v1.9/manual/variables-and-scoping/#scope-of-variables
says the scope of `do` is local(hard) which means:

1. Hard scope: If `x` is not already a local variable and assignment occurs inside of any hard scope construct (i.e. within a `let` block, function or macro body, comprehension, or generator), a new local named `x` is created in the scope of the assignment;

and the result of above MWE seem to contradict this. (Julia 1.9 here)

So, VSCode is right but scope rules seem to be not fulfilled or misinterpreted by me.

1 Like

Scope experts needed here!

I think removing the `do` syntax always makes things clearer:

``````julia> function foo()
x = 1
y = [1,2]
foreach(el -> x += 1, y)
return x
end
foo (generic function with 1 method)

julia> foo()
3
``````

the anonymous function `el -> x += 1` is closing over the `x` value. In general it is not a good idea to modify closed over variables, but that whatâ€™s going on there. I think it is a linker bug, there.

1 Like

I think this example is a bit misleading.
It would better be written as:

``````function foo2()
a=[1,2,3]
y=0
foreach( x-> y=x, a)
y
end
``````

Or even more explicit:

``````julia> function foo3()
a=[1,2,3]
y=0
function f(x)
y=x
end
f(3)
y
end
foo3 (generic function with 1 method)

julia> foo3()
3
``````

So, the remaining question is:
Why does `function f(x)` inside `foo3` not introduce a new local scope with a local `y` ?
Instead it inherits the scope of `foo3`.

Or: Why is `local` needed here:

``````julia> function foo4()
a=[1,2,3]
y=0
function f(x)
local y=x
end
f(3)
y
end
foo4 (generic function with 1 method)

julia> foo4()
0
``````

I canâ€™t find a good explanation from the docs of scope.

It seems to be clear here:

"When `x = <value>` occurs in a local scope, Julia applies the following rules to decide what the expression means based on where the assignment expression occurs and what `x` already refers to at that location:

1. Existing local: If `x` is already a local variable, then the existing local `x` is assigned;"

The â€ślocal scopeâ€ť rules are very comprehensively explained here: Scope of Variables Â· The Julia Language

(though I admit one learns that by doing mostly, than by reading the docs)

The docs excerpt you quoted above does explain whatâ€™s going on here â€“ `likelihood` is an already present local variable, after all.

Regarding the original issue: Itâ€™s a bug in the linter, yes. The scope analysis done there is by no means perfect.

1 Like

Found the right part:

1. Inner function scopes are just like any other nested local scope. In particular, if a variable is already a local outside of an inner function and you assign to it in the inner function, the outer local variable is updated.

Thanks very much @oheil, I have never thought the issue was with `foreach`

I simple substitution by `for paire in a` instead of `foreach` has solved the problem.

1 Like

One more reason to avoid nested functions when possible.

Note one additional danger in this case: I donâ€™t see any guarantee concerning the order of evaluation of `foreach`, meaning that in principle the result of such a calculation can change, and there could be even data races.

1 Like