Can you define variables inside a comprehension?

julia> M = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> M = (M + M') ./ 2.0
2×2 Matrix{Float64}:
 1.0  2.5
 2.5  4.0

julia> M = [1 2; 3 4]
2×2 Matrix{Int64}:
 1  2
 3  4

julia> [ x = (x + x') ./ 2.0 for x in [M] ]
1-element Vector{Matrix{Float64}}:
 [1.0 2.5; 2.5 4.0]

julia> M
2×2 Matrix{Int64}:
 1  2
 3  4

Is there a way to redefine/mutate a variable inside a comprehension?
Or are all things supposed to be always be local inside a comprehension?

You can change an existing variable from outer scope as follows:

julia> function f(outer_var)
           [
               begin
                   outer_var = i
               end
               for i in 1:100 ]
           return outer_var
       end
f (generic function with 1 method)

julia> f(1)
100

As a matter of style, I’d say it’s better that way.

2 Likes

You can mutate a variable inside a comprehension but I wouldn’t recommend it as its very non-standard/confusing. If you really want to do it then

julia> M = [1.0 2; 3 4]
2×2 Matrix{Float64}:
 1.0  2.0
 3.0  4.0

julia> [x .= (x + x') ./ 2.0 for x in [M]]
1-element Vector{Matrix{Float64}}:
 [1.0 2.5; 2.5 4.0]

julia> M
2×2 Matrix{Float64}:
 1.0  2.5
 2.5  4.0

(Note that you need to get the type of M right to mutate it like this.)

If you don’t want the resulting collection, a much cleaner way would be to declare a function and broadcast over the array.

julia> dosomething!(x) = (x .= (x + x') ./ 2.0)
dosomething! (generic function with 1 method)

julia> M = [1.0 2; 3 4]
2×2 Matrix{Float64}:
 1.0  2.0
 3.0  4.0

julia> dosomething!.([M])
1-element Vector{Matrix{Float64}}:
 [1.0 2.5; 2.5 4.0]

julia> M
2×2 Matrix{Float64}:
 1.0  2.5
 2.5  4.0

or

julia> M = [1.0 2; 3 4]
2×2 Matrix{Float64}:
 1.0  2.0
 3.0  4.0

julia> foreach(x -> x .= (x + x') ./ 2.0, [M])

julia> M
2×2 Matrix{Float64}:
 1.0  2.5
 2.5  4.0
3 Likes