# Closure with let block: Simpler syntax for capturing variables?

**URL:** <https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740>\
**Category:** General Usage\
**Tags:** closure\
**Created:** [January 13, 2025, 7:57pm UTC](https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740 "2025-01-13T19:57:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [January 13, 2025, 7:57pm UTC](https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740/1 "2025-01-13T19:57:18Z")

</div>

The example is taken from the post ["A Tragedy of Julia’s Type System" - #30 by foobar\_lv2](https://discourse.julialang.org/t/a-tragedy-of-julia-s-type-system/124619/30)

```julia
function f()
   x = 0
   if false x=1 end
   g = let x=x
      () -> x
   end
end

```

This form is suggested in the manual, and indeed the `@code_warntype` shows no warning.

My question is about the syntax `x=x`. Sometimes I want to captures several variables, and get `let foo=foo, bar=bar, ...`. It seems stupid to repeat the same words, and indeed it reduces the readability when the variables’ names are long.

I’m wondering if it’s possible to have syntax like `let ;foo, bar`, as in the function call with keywords we can do `fn(; foo, bar)`.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [January 13, 2025, 8:41pm UTC](https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740/2 "2025-01-13T20:41:46Z")

</div>

Here’s one way you could do it:

```julia
macro localize(args...)
    to_localize = args[1:end-1]
    ex = args[end]
    esc(Expr(:let, Expr(:block, (:($x=$x) for x ∈ to_localize)...), ex))
end

```

and then

```julia-repl
julia> @macroexpand @localize x y z () -> x + y + z
:(let x = x, y = y, z = z
      ()->begin
              #= REPL[11]:1 =#
              x + y + z
          end
  end)

```

Then your example would be written

```julia
function f()
   x = 0
   if false x=1 end
   g = @localize x () -> x
   end
end

```

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [January 13, 2025, 8:54pm UTC](https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740/3 "2025-01-13T20:54:08Z")

</div>

Nice, just had the same idea … albeit with a slightly different syntax resembling closures in C++:

```julia
using MacroTools

macro closure(expr)
    @assert @capture expr ([binds__](args__) -> body_)
    @assert all(x -> isexpr(x, Symbol), binds)
    bindings = [:($(esc(v)) = $(esc(v))) for v in binds]
    Expr(:let, Expr(:block, bindings...), Expr(:->, Expr(:tuple, esc.(args)...), esc(body)))
end

```

To be used like …

```julia-repl
julia> @macroexpand @closure [x, y](z) -> x*z + y
:(let x = x, y = y
      (z,)->begin
              #= REPL[73]:1 =#
              x * z + y
          end
  end)

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [January 13, 2025, 9:11pm UTC](https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740/4 "2025-01-13T21:11:36Z")

</div>

If we’re looking for macro workarounds, there’s also FastClosures.jl, which identifies the captured variables for you:

```julia
using FastClosures

function f()
   x = 0
   if false x=1 end
   g = @closure () -> x
end

```

---

<div class="post-metadata">

**Author:** ![linwaytin](https://avatars.discourse-cdn.com/v4/letter/l/898d66/32.png) [@linwaytin](https://discourse.julialang.org/u/linwaytin)\
**Post date:** [January 14, 2025, 12:46am UTC](https://discourse.julialang.org/t/closure-with-let-block-simpler-syntax-for-capturing-variables/124740/5 "2025-01-14T00:46:40Z")

</div>

Thank you guys! Hopefully some of these efforts can be merged into the language itself.
