Invalid quoted expression when assigning tuple to multiple variables

This is valid code:

julia> x,y = 1,2
(1, 2)

julia> x
1

julia> y
2

But, the quoted expression isn’t correct and cannot be evaluated…

julia> :(x,y = 1,2) |> dump
Expr
  head: Symbol tuple
  args: Array{Any}((3,))
    1: Symbol x
    2: Expr
      head: Symbol =
      args: Array{Any}((2,))
        1: Symbol y
        2: Int64 1
    3: Int64 2

julia> :(x,y = 1,2) |> eval
ERROR: syntax: invalid named tuple element "x"

Looks like it’s parsing it as a 3-tuple of x, y=1, and 2 instead. Obviously, that won’t work.

If I wrap everything in parentheses then it is fine.

julia> :((x,y) = (1,2)) |> dump
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Expr
      head: Symbol tuple
      args: Array{Any}((2,))
        1: Symbol x
        2: Symbol y
    2: Expr
      head: Symbol tuple
      args: Array{Any}((2,))
        1: Int64 1
        2: Int64 2

julia> :((x,y) = (1,2)) |> eval
(1, 2)

Is this a parsing bug?

This isn’t a parsing bug but it can be confusing because the () which follows the : in a quoted expression is inside the quote, not part of the quoting syntax.

This might be clearer if you observe how the single : prefix interacts with some other syntactic forms:

julia> :(1,2)
:((1, 2))

julia> :[1,2]
:([1, 2])

julia> :"x = $x"
:("x = $(x)")

julia> :@hi 1 2 3
:(#= REPL[20]:1 =# @hi 1 2 3)

Notice how all these came out quoted: none actually required an extra set of parentheses. (In the language of the parser, the : quotes any syntactic “atom” following it.)

So your confusion about the original example is the difference between having vs not having parentheses in the following:

julia> quote
           (x,y = 1,2)
           x,y = 1,2
       end
quote
    #= REPL[22]:2 =#
    (x, y = 1, 2)
    #= REPL[22]:3 =#
    (x, y) = (1, 2)
end
2 Likes

This is a great explanation, thank you! I always thought the parenthesis is part of the quoting syntax.