I think it is probably important to note that interpolating a variables and expression in an expression lead to slightly different things.
julia> v = (1,2,3)
julia> dump(:(a in $v))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol in
2: Symbol a
3: Tuple{Int64,Int64,Int64}
1: Int64 1
2: Int64 2
3: Int64 3
julia> dump(:(a in (1,2,3)))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol in
2: Symbol a
3: Expr
head: Symbol tuple
args: Array{Any}((3,))
1: Int64 1
2: Int64 2
3: Int64 3
and if you don’t interpolate the expression you get.
julia> dump(:(a in :((1,2,3))))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol in
2: Symbol a
3: Expr
head: Symbol quote
args: Array{Any}((1,))
1: Expr
head: Symbol tuple
args: Array{Any}((3,))
1: Int64 1
2: Int64 2
3: Int64 3
So really what it looks like interpolating the expression does is to unwrap the inner expression and pass it as an argument. I.E. The respective difference is:
julia> Expr(:call, :in, :a, (1,2,3))
:(a in (1, 2, 3))
julia> Expr(:call, :in, :a, :((1,2,3)))
:(a in (1, 2, 3))
julia> Expr(:call, :in, :a, Expr(:quote, :(1,2,3)))
:(a in $(Expr(:quote, :((1, 2, 3)))))