Tuples Broadcast and Expression Tree

I am trying to understand Metaprogramming in Julia. I wrote the following code


function traversal!(x::Expr,mem)
    for xx in x.args
        if isa(xx,Expr)
            push!(mem,xx)
            traversal!(xx,mem)
        end
    end
end

expr=:(sum((x-cos(W2*sin(W1*x+b1)+b2))^2))
mem=[]
a=traversal!(expr,mem)

I expect mem to be an Array with 8 elements


:((x - cos(W2 * sin(W1 * x + b1) + b2)) ^ 2)
:(x - cos(W2 * sin(W1 * x + b1) + b2))
:(cos(W2 * sin(W1 * x + b1) + b2))
:(W2 * sin(W1 * x + b1) + b2)
:(W2 * sin(W1 * x + b1))
:(sin(W1 * x + b1))
:(W1 * x + b1)
:(W1 * x)

Result is as expected however when i replace the expression

expr=:(sum((x-cos(W2*sin(W1*x+b1)+b2))^2))

with

expr=:(sum((x-cos.(W2*sin.(W1*x+b1)+b2)).^2))

output becomes

:((x - cos.(W2 * sin.(W1 * x + b1) + b2)) .^ 2)
:(x - cos.(W2 * sin.(W1 * x + b1) + b2))
:(cos.(W2 * sin.(W1 * x + b1) + b2))
:((W2 * sin.(W1 * x + b1) + b2,))
:(W2 * sin.(W1 * x + b1) + b2)
:(W2 * sin.(W1 * x + b1))
:(sin.(W1 * x + b1))
:((W1 * x + b1,))
:(W1 * x + b1)
:(W1 * x)

Why do i get those extra Tuple Symbols?

Crosspost: Julia traversing the expression tree containing broadcast results in unintended tuples - Stack Overflow

This is how broadcast expressions are stored. The tuple will host all arguments to the function which happens to be 1 in your case.

julia> dump(:(f.(x)))
Expr
  head: Symbol .
  args: Array{Any}((2,))
    1: Symbol f
    2: Expr
      head: Symbol tuple
      args: Array{Any}((1,))
        1: Symbol x
      typ: Any
  typ: Any

julia> dump(:(f.(x, y)))
Expr
  head: Symbol .
  args: Array{Any}((2,))
    1: Symbol f
    2: Expr
      head: Symbol tuple
      args: Array{Any}((2,))
        1: Symbol x
        2: Symbol y
      typ: Any
  typ: Any

julia> dump(:(f.(x, y, z)))
Expr
  head: Symbol .
  args: Array{Any}((2,))
    1: Symbol f
    2: Expr
      head: Symbol tuple
      args: Array{Any}((3,))
        1: Symbol x
        2: Symbol y
        3: Symbol z
      typ: Any
  typ: Any