# ANN LegibleLambdas.jl

**URL:** <https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199>\
**Category:** Package Announcements\
**Created:** [February 26, 2019, 2:45am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199 "2019-02-26T02:45:47Z")\
**Posts on this page:** 9\
**Page:** 1

<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:** [February 26, 2019, 2:45am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/1 "2019-02-26T02:45:47Z")

</div>

[LegibleLambas.jl](https://github.com/MasonProtter/LegibleLambdas.jl) is a package for making anonymous functions whose names are their expressions, ie.

```julia
julia> f = @λ(x -> x + 1)
(x -> x + 1)

julia> f(1.0)
2.0

```

The primary use-case I see for this functionality is for functions which return functions (closures). Suppose I have a function `D` which operates on a function and gives it’s (finite difference) derivative, I can use LegibleLambdas

```julia
D(f, ϵ=1e-10) = @λ(x -> (f(x+ϵ)-f(x))/ϵ)

```

so that when a user wants to know what `D(sin)` is, they are shown

```julia
julia> D(sin)
(x -> (sin(x + 1e-10) - sin(x)) / 1e-10)

```

instead of something like

```julia
julia> D(sin)
#1 (generic function with 1 method)

```

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [February 26, 2019, 4:00am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/2 "2019-02-26T04:00:10Z")

</div>

It would be nice to do something like this for display of short functions in base; see also

[https://github.com/JuliaLang/julia/issues/24347](https://github.com/JuliaLang/julia/issues/24347)

---

<div class="post-metadata">

**Author:** ![Roger-luo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roger-luo/32/3399_2.png) [@Roger-luo](https://discourse.julialang.org/u/Roger-luo)\
**Post date:** [February 26, 2019, 6:01am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/3 "2019-02-26T06:01:43Z")

</div>

Nice work! I’m already using this in our next release of Yao.jl!

---

<div class="post-metadata">

**Author:** ![Roger-luo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roger-luo/32/3399_2.png) [@Roger-luo](https://discourse.julialang.org/u/Roger-luo)\
**Post date:** [February 26, 2019, 6:02am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/4 "2019-02-26T06:02:28Z")

</div>

Will it be possible to have this feature directly in `julia`? So short lambda’s printing will be something like `LegibleLambdas` by default. We do get nothing from current printings…

---

<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:** [February 26, 2019, 6:48pm UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/5 "2019-02-26T18:48:44Z")

</div>

> [@Roger-luo](#):
>
> Nice work! I’m already using this in our next release of Yao.jl!

I should have mentioned in the original post that this would probably have just rotted away on my list of abandoned repositories if you hadn’t come along with your PR to overhaul the internals and fix a few problems I was unable to figure out, so thank you Roger!

---

<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 9, 2021, 11:40pm UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/6 "2021-01-09T23:40:00Z")

</div>

Just an update, it had been bothering me in the back of my head for some time now that LegibleLambdas was producing slow closures. I’ve now updated it to version 0.3.0 where closures do not impose a runtime performance overhead! I’ve also lightened the dependancies.

```julia
julia> using LegibleLambdas

julia> f(x) = @λ y -> x + y;

julia> f(1)
(y -> 1 + y)

julia> f(2)
(y -> 2 + y)

julia> let x = Ref(1), y = Ref(2)
           @btime f($x[])($y[])
       end;
  1.299 ns (0 allocations: 0 bytes)

```

```julia
julia> D1(f, ϵ=1e-10) = @λ(x -> (f(x+ϵ) - f(x))/ϵ);

julia> D2(f, ϵ=1e-10) = x -> (f(x+ϵ) - f(x))/ϵ;

julia> let x = Ref(1.0)
           @btime D1(sin)($x[])
           @btime D2(sin)($x[])
       end;
  12.975 ns (0 allocations: 0 bytes)
  12.975 ns (0 allocations: 0 bytes)

julia> D1(sin)
(x -> ((sin)(x + 1.0e-10) - (sin)(x)) / 1.0e-10)

julia> D2(sin)
#14 (generic function with 1 method)

```

Happy λs.

---

<div class="post-metadata">

**Author:** ![xzackli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xzackli/32/38301_2.png) [@xzackli](https://discourse.julialang.org/u/xzackli)\
**Post date:** [January 10, 2021, 3:04am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/7 "2021-01-10T03:04:57Z")

</div>

What was the performance culprit behind the slow closures? I have some vague memory that there’s a famous issue with closure performance, is that this?

---

<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 10, 2021, 3:12am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/8 "2021-01-10T03:12:25Z")

</div>

The culprit was relying on `Base.@locals` to fetch variable names and values which is slow and won’t be optimized away by the compiler. What I realized recently was that closures actually store the names and values of the bound variables in themselves, so there was no need for `Base.@locals`.

Here’s a minimal working example of the problem:

```julia
julia> f(x) = (Base.@locals(), y -> x + y)
f (generic function with 1 method)

julia> let x = Ref(1), y = Ref(2)
           @btime f($x[])[2]($y[])
       end
  103.571 ns (4 allocations: 608 bytes)
3

```

---

<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 10, 2021, 3:38am UTC](https://discourse.julialang.org/t/ann-legiblelambdas-jl/21199/9 "2021-01-10T03:38:38Z")

</div>

> [@xzackli](#):
>
> I have some vague memory that there’s a famous issue with closure performance, is that this?

That’s a separate issue. LegibleLambdas will suffer from that issue to the same extent that regular illegible closures do. Here’s an example:

```julia
julia> using LegibleLambdas

julia> f(x) = y -> begin
           x = x + 1.0
           x + y
       end
f (generic function with 1 method)

julia> g(x) = @λ y -> begin
           x = x + 1.0
           x + y
       end
g (generic function with 1 method)

julia> let x = Ref(1), y = Ref(2)
           @btime f($x[])($y[])
           @btime g($x[])($y[])
       end
  48.969 ns (3 allocations: 48 bytes)
  48.582 ns (3 allocations: 48 bytes)
4.0

```

One thing that’s nice though about LegibleLambdas is that it can help diagnose this problem:

```julia
julia> g(1)
(y -> begin
          Core.Box(1) = Core.Box(1) + 1.0
          Core.Box(1) + y
      end)

```

Though, the ‘legible’ printing leaves something to be desired here. I basically just walked through the syntax tree and replaced `x` with `1`, so in the presence of rebindings and such, it’s kinda nonsense. Where is says `Core.Box(1)`, it’s really `Core.Box(x)`.
