Closures and Let Blocks

Anyone have any basic examples of when to use/what the effects are of having a let block along with a closure?

I’ve been looking to learn more about functional programming in Julia and reading through the manual, but I don’t think I understand the uses of a let block from reading the docs.

Any help is appreciated, and any more resources in functional programming with Julia (or in general ) would be greatly appreciated!!

The classic case is when you want to create a new binding that will be captured in a closure. For example if you’re modifying a value in a while loop and capturing it, then that might not do what you want:

function fib_closures(n)
    fns = []
    a = b = 1
    while b <= n
        push!(fns, x -> x + b)
        a, b = b, a + b
    end
    return fns
end
julia> [f(0) for f in fib_closures(10)]
5-element Vector{Int64}:
 13
 13
 13
 13
 13

If you want each captured closure to get a private copy of b then you need to use let to create a fresh binding for each one (which can have the same name):

function fib_closures(n)
    fns = []
    a = b = 1
    while b <= n
        let b = b
            push!(fns, x -> x + b)
        end
        a, b = b, a + b
    end
    return fns
end
julia> [f(0) for f in fib_closures(10)]
5-element Vector{Int64}:
 1
 2
 3
 5
 8

Thank you, this helps a bunch!
I also understand there’s some well known type stability issues when referencing enclosed variables. I’ve heard that a let block can help with speed things up a bit, though I don’t quite understand why. Any insights on this?

See Performance of captured variable in the manual.

Thank you! Must’ve slipped through the cracks while going through the manual. Also, I’ve been using julia-repl in emacs quite a bit, so thanks for that!