Julia Expression Walking
Expression walking is a recursive walk through a code expression, piece by piece. It visits the head and the parts, changes leaves, and rebuilds the expression.
A parsed expression has a head and three parts
Meta.parse turns text into an expression. The head and the part count show its shape.
ex = Meta.parse("2 + 3")
println(ex.head)
println(length(ex.args))
println(ex)A walk can count every piece
The walk adds one for the expression itself and one for each leaf, recursing into nested parts.
function count_nodes(x)
if x isa Expr
return 1 + sum(count_nodes(a) for a in x.args)
else
return 1
end
end
println(count_nodes(:(2 + 3 * 4)))A walk can change leaves and rebuild
Numbers double, names stay, and the rebuilt expression keeps its shape.
function double_numbers(x)
if x isa Expr
return Expr(x.head, map(double_numbers, x.args)...)
elseif x isa Number
return x * 2
else
return x
end
end
println(double_numbers(:(2 + 3)))
println(double_numbers(:(2 + 3 * 4)))Example
function count_nodes(x)
if x isa Expr
return 1 + sum(count_nodes(a) for a in x.args)
else
return 1
end
end
function replace_x(x)
if x isa Expr
return Expr(x.head, map(replace_x, x.args)...)
elseif x === :x
return 5
else
return x
end
end
println(count_nodes(:(x + 1)))
println(replace_x(:(x + 1)))
println(replace_x(:(x * x)))Key points
- Head: The head names the kind of expression, such as a call.
- Parts list: ex.args holds the pieces of the expression in order.
- Leaf: A leaf is a piece that is not an expression, such as a number or a name.
- Rebuild: A walk rebuilds an expression from its head and its changed parts.
- Use expression walking to inspect and change code structure piece by piece.
In this example, count_nodes counts four pieces in x plus 1, replace_x swaps x for 5 in x plus 1, and replace_x swaps both copies of x in x times x.
Note
A walk must handle both expressions and leaves, or it will miss pieces.
Try it Yourself
Edit the code, then press Run.
Running is simulated · JuliaHub
Exercise
What does a walk do with a leaf?