Constructing a let block

Can someone help explain why the let block only works up to the second argument?

How would I rewrite this to account for all arguments?

julia> a = 4
4

julia> eval(Expr(:let, :(b = a), :(h = b+2), :(d = b+3)))
6

Thanks.

Just ask Julia how it constructs the let block you actually wanted:

julia> Meta.show_sexpr(:(let b=a
           h = b+2
           d = b+3
       end))
(:let, (:(=), :b, :a), (:block,
    :(#= REPL[16]:2 =#),
    (:(=), :h, (:call, :+, :b, 2)),
    :(#= REPL[16]:3 =#),
    (:(=), :d, (:call, :+, :b, 3))
  ))

Or more simply, that’s using a begin/end block to group the multiple expressions:

julia> eval(Expr(:let, :(b = a), :(begin; h = b+2; d = b+3; end)))
7
2 Likes

Is there a way to construct this? I tried the following:

julia> expr = Expr(:let)
:($(Expr(:let)))

julia> push!(expr.args, Expr(:(=), b, a))
1-element Vector{Any}:
 :(4 = 4)

julia> push!(expr.args, Expr(:block))
2-element Vector{Any}:
 :(4 = 4)
 quote
end

julia> push!(expr.args[2].args, Expr(:(=), h, b+2))
1-element Vector{Any}:
 :(4 = 6)

julia> eval(expr)
ERROR: syntax: invalid let syntax
Stacktrace:
 [1] top-level scope
   @ none:1
 [2] eval
   @ Core .\boot.jl:385 [inlined]
 [3] eval(x::Expr)
   @ Base.MainInclude .\client.jl:491
 [4] top-level scope
   @ REPL[150]:1

You’re missing a good deal of quoting there. You want:

expr = Expr(:let)
push!(expr.args, Expr(:(=), :b, :a))
push!(expr.args, Expr(:block))
push!(expr.args[2].args, Expr(:(=), :h, :(b+2)))
2 Likes