juliaijulia-notebook

Chained variable assignment in Julia


I'm puzzled by how Julia handles the block of code below:

a = [1,2,3]
a .= a/2 .= o = a .* 2

The output for both 'a' and 'o' is [2,4,6]. However, I don't understand why the result for 'a' is the same as if I had used a .= a*2. Is a/2 treated as a variable and passed the array [2,4,6] (the result of a*2)? And then this "variable" a/2 is passed to a? I would have expected a to have stayed as [1,2,3]. I'm uncertain as to whether Julia executes these operations in a specific order.


Solution

  • The expression a / 2 creates a new array which initially contains the values you expect ([1,2,3]) however the contents of that array are immediately overwritten by a broadcast assignment with the contents in the right hand side array.

    Let's break down the entire expression, Julia can help us:

    julia> :(a .= a/2 .= o = a .* 2)
    :(a .= (a / 2 .= (o = a .* 2)))
    

    By looking at the parentheses inserted when the Expr is printed we see the subexpressions a bit more clearly. As you can see the top expression is a .= (result of everything on RHS).

    Let's evaluate it in the REPL:

    julia> o = a .* 2
    3-element Vector{Int64}:
     2
     4
     6
       
    julia> a / 2 .= (o = a .* 2)
    3-element Vector{Float64}:
     2.0
     4.0
     6.0
                      
    julia> a .= (a / 2 .= (o = a .* 2))
    3-element Vector{Int64}:
     2
     4
     6
    

    As you can see the array created by a / 2 is a Float64 array and the values are therefore converted and then converted back to Int64 when put into a.

    We can make the right hand side expression even more explicit by using Meta.show_sexpr.

    julia> :(a/2 .= o = a .* 2) |> Meta.show_sexpr
    (:.=, (:call, :/, :a, 2), (:(=), :o, (:call, :.*, :a, 2)))
    

    let's add some whitespace for clarity:

    (:.=,
      (:call, :/, :a, 2),
      (:(=),
        :o,
        (:call, :.*, :a, 2)))
    

    so this expression is broadcast assigning to the value that is returned by calling the / function on the arguments a and 2. The value that is assigned is what the assignment o = a * 2 returns.