# Documenting when the closure "bug" (#15276) binds, and how to avoid it for introductory users

**URL:** https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642
**Category:** General Usage
**Tags:** closure
**Created:** [July 24, 2018, 11:13pm UTC](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642 "2018-07-24T23:13:44Z")
**Posts on this page:** 5
**Page:** 3

<div class="post-metadata">

### Author: ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)
#### Post date: [July 26, 2018, 5:49pm UTC](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642/41 "2018-07-26T17:49:41Z")

</div>

> [@jlperla](#):
>
> is that beginners are best not given code to copy that has lots of parametric user defined types

Sure, in fact being able to avoid types entirely, and then use types but avoid parameters, and then add parameters, was a major design criterion. And it’s true that abstract field types are a performance problem, but could you expand on the issue with parameters? I’m wondering if there’s some performance issue with type parameters specifically that I’m not thinking of.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [July 26, 2018, 5:59pm UTC](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642/42 "2018-07-26T17:59:11Z")

</div>

> Lecturing people on asking the wrong question can also be helpful, but if you let there be a direct answer first, it decreases the signal to noise ratio. I hate that I had to type so much defending why I was asking the question and that people were wrongly assuming my intentions. If people had just let @mbauman answer first, and did the lecturing later, it would have helped.

You should note that I had three “failed” attempts at bringing light to your question before we got to the answer you marked as the “solution.” The first was too in-depth, the second was too simplistic, and the third was more tangential than anything else. It often takes a back-and-forth for questioners and answerers to get on the same page. I think everyone involved here was helpful in getting this thread to that point.

It’s not always clear what words will resonate with a poster and answer their true question — I’d say that “don’t worry about it unless you’re teaching optimizations” could be just as valid of an answer as the post you liked from me… and I certainly wouldn’t consider it as a ‘lecture’ on asking the wrong question. Remember that folks here are volunteering their time, might have limited time, might be expressing their thoughts in a foreign language, or just might not be the best writers in the first place — we’re not here because we studied persuasive writing in college. I always try to assume the best intentions of the folks on the other side of the screen.

---

<div class="post-metadata">

### Author: ![jlperla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlperla/32/34332_2.png) [@jlperla](https://discourse.julialang.org/u/jlperla)
#### Post date: [July 26, 2018, 6:52pm UTC](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642/43 "2018-07-26T18:52:39Z")

</div>

> [@jeff.bezanson](#):
>
> in fact being able to avoid types entirely

Couldn’t agree more. I hope type-annotation (except where strictly necessary) free example code becomes the goal for introductory tutorials.

> [@jeff.bezanson](#):
>
> , but could you expand on the issue with parameters?

Sorry for the imprecision. I used the term “parameters” in the sense of a collection of model parameters (e.g. Parameters.jl approach), not template parameters. There are no performance issues with parametric templates when used correctly. The problem is that beginners have trouble using them correctly. But there is an easy solution:

```julia
params = (x = 0.1, y = [1 2 3], z = [1.0 2.0 3.0])
f(p) = p.x
f(params)

```

is clearer, the same performance, and without all of the places for mistakes as examples such as:

```julia
struct ParameterType{F <: AbstractFloat, I2 <: Int, F2 <: AbstractFloat,
                     AV1<: AbstractVector{Int}, AV2 <: AbstractVector{F2}}
  x::F
  y::AV
  z::AV2
end  
f(p::ParameterType) = p.x
params = ParameterType(0.1, [1 2 3], [1.0 2.0 3.0])
f(params)

```

(I should point out that I don’t have the patience to test the 2nd case, so I am sure there are mistakes… which helps prove my point.)

> [@mbauman](#):
>
> You should note that I had three “failed” attempts at bringing light to your question before we got to the answer you marked as the “solution.”

Yes, and thank you for your patience. All of your attempts were trying to answer my question, or trying clarify what I was getting at. Patience with my lousy, imprecise, and frequently ill-informed questions is one of the reasons I love the Julia community… I even love people challenging the basic assumptions behind a question. I would just prefer if the discourse culture didn’t mix the two together.

---

<div class="post-metadata">

### Author: ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)
#### Post date: [July 26, 2018, 7:08pm UTC](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642/44 "2018-07-26T19:08:30Z")

</div>

> [@jlperla](#):
>
> ```julia
> params = (x = 0.1, y = [1 2 3], z = [1.0 2.0 3.0])
> 
> ```

Yes, excellent! Agreed, I’m glad we have named tuples now.

---

<div class="post-metadata">

### Author: ![aaowens](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aaowens/32/12101_2.png) [@aaowens](https://discourse.julialang.org/u/aaowens)
#### Post date: [July 26, 2018, 7:45pm UTC](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642/45 "2018-07-26T19:45:39Z")

</div>

I came up with an example of forming closures in a loop which I think is representative of looping over parameter values and solving a non-linear equation. In 0.6 this hits the bug and has bad performance. However, I am happy to see that on the latest 0.7 master, there is no problem. In fact, performance is about 10% faster than 0.6 even in the fast case.

I will stop worrying about this bug myself.

Example here::

```julia
using BenchmarkTools

struct Wow2
       x::Float64
       y::Float64
       i::Float64
end

function test1(x, A, B)
       y = 3.
       for i in eachindex(A)
              b = B[i]
              f(z) = b^2 + x*y*z
              A[i] = f(b)
       end
end
function test1_let(x, A, B)
       y = 3.
       for i in eachindex(A)
              b = B[i]
              f = let b = b, x = x, y = y
                     z-> b^2 + x*y*z
              end
              A[i] = f(b)
       end
end
(f::Wow2)(z) = f.i^2 + f.x*f.y*z
function test2(x, A, B)
       y = 3.
       for i in eachindex(A)
              b = B[i]
              f = Wow2(x, y, b)
              A[i] = f(b)
       end
end
N = 100000
A1 = zeros(N)
A2 = ones(N)
B = rand(N)
@btime test1(2., $A1, $B)
@btime test1_let(2., $A1, $B)
@btime test2(2., $A2, $B)
A1 == A2

```

0.6

```julia
julia> @btime test1(2., $A1, $B)
  46.893 ms (700000 allocations: 10.68 MiB)

julia> @btime test1_let(2., $A1, $B)
  107.480 μs (0 allocations: 0 bytes)

julia> @btime test2(2., $A2, $B)
  107.486 μs (0 allocations: 0 bytes)

```

0.7

```julia
julia> @btime test1(2., $A1, $B)
  86.699 μs (0 allocations: 0 bytes)

julia> @btime test1_let(2., $A1, $B)
  86.693 μs (0 allocations: 0 bytes)

julia> @btime test2(2., $A2, $B)
  86.627 μs (0 allocations: 0 bytes)

```

[Previous page](https://discourse.julialang.org/t/documenting-when-the-closure-bug-15276-binds-and-how-to-avoid-it-for-introductory-users/12642.md?page=2)
