# Destroying type stabiliy by creating "chaining" closures of functions

**URL:** <https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990>\
**Category:** General Usage\
**Tags:** question, type-stability\
**Created:** [September 15, 2018, 8:37am UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990 "2018-09-15T08:37:02Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 8:37am UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/1 "2018-09-15T08:37:02Z")

</div>

I’ve found myself doing things like the below out of convenience. I’ve noticed that type stability is destroyed however. Is there a better way of achieving the same thing?

```julia
julia> struct Foo{T}
       a::T
       end

julia> (foo::Foo)() = foo.a

julia> foo = Foo(1)
Foo{Int64}(1)

julia> @code_warntype foo()
Body::Int64
1 1 ─ %1 = (Base.getfield)(foo, :a)::Int64 │╻ getproperty
  └── return %1 │ 

julia> bar() = foo()
bar (generic function with 1 method)

julia> @code_warntype bar()
Body::Any
1 1 ─ %1 = (Main.foo)()::Any │
  └── return %1 │

julia> baz() = () -> foo() + foo()
baz (generic function with 1 method)

julia> @code_warntype baz()
Body::getfield(Main, Symbol("##3#4"))
1 1 ─ %1 = %new(Main.:(##3#4))::Core.Compiler.Const(getfield(Main, Symbol("##3#4"))(), false)
  └── return %1    

julia> versioninfo()
Julia Version 0.7.1-pre.0
Commit 36cddc1006 (2018-08-09 00:19 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin17.7.0)
  CPU: Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.0 (ORCJIT, broadwell)
Environment:
  JULIA_NUM_THREADS = 4

```

The reason I’m doing this because the functions keep a reference to the original objects. This means I can close a function over a mutable struct, then later update it, and these changes are reflected in the closure:

```julia
julia> mutable struct Foo{T}
       a::T
       end

julia> (foo::Foo)() = foo.a

julia> foo = Foo(1)
Foo{Int64}(1)

julia> bar() = foo()
bar (generic function with 1 method)

julia> bar()
1

julia> foo.a = 2
2

julia> bar()
2

```

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [September 15, 2018, 10:36am UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/2 "2018-09-15T10:36:57Z")

</div>

```nohighlight
julia> struct Foo{T}
              a::T
         end
julia> (foo::Foo)() = foo.a
julia> const foo = Foo(1)
Foo{Int64}(1)
julia> bar() = foo()
bar (generic function with 1 method)
julia> @code_warntype bar()
Body::Int64
1 1 ─ return 1

```

Can’t you make `foo` constant? All non const globals have this problem, since you can assign anything to them at any point in the program.

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 12:23pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/3 "2018-09-15T12:23:29Z")

</div>

Thanks! I thought I couldn’t do that, but it seems I can, but now I’m not sure what `const` actually means.

```julia
julia> mutable struct Foo{T}
       a::T
       end

julia> (foo::Foo)() = foo.a

julia> const foo = Foo(1)
Foo{Int64}(1)

julia> bar() = foo()
bar (generic function with 1 method)

julia> @code_warntype bar()
Variables:
  #self# <optimized out>

Body:
  begin 
      return (Core.getfield)(Main.foo, :a)::Int64
  end::Int64

julia> bar()
1

julia> foo.a = 2
2

julia> bar()
2

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [September 15, 2018, 12:40pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/4 "2018-09-15T12:40:10Z")

</div>

> [@jcook](#):
>
> but now I’m not sure what `const` actually means.

Marking a global as `const` tells the compiler that the variable is not going to change (neither value nor type) since constants will only be assigned once. Be aware that this only works for global scope. See [here](https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Constants-1).

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 1:20pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/5 "2018-09-15T13:20:41Z")

</div>

It seems as though the scope dependent behaviour of `const` is quite nuanced, especially compared to the same word in c++.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [September 15, 2018, 1:26pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/6 "2018-09-15T13:26:57Z")

</div>

Is it? In the global scope, it just says that the binding cannot be changed. In local scope, it’s an error.

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 2:23pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/7 "2018-09-15T14:23:41Z")

</div>

I misspoke, I mean nuanced in general. This here is a definite gotcha:

```julia
julia> mutable struct Bar{T}
           a::T
       end

julia> struct Foo{T}
           a::T
       end

julia> const foo = Foo(Bar(1))
Foo{Bar{Int64}}(Bar{Int64}(1))

julia> foo.a.a = 2
2

```

But this throws:

```julia
julia> foo.a = Bar(2.0)
ERROR: MethodError: Cannot `convert` an object of type Bar{Float64} to an object of type Bar{Int64}
Closest candidates are:
  convert(::Type{T}, ::T) where T at essentials.jl:154
  Bar{Int64}(::Any) where T at REPL[1]:2
Stacktrace:
 [1] setproperty!(::Foo{Bar{Int64}}, ::Symbol, ::Bar{Float64}) at ./sysimg.jl:19
 [2] top-level scope at none:0

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [September 15, 2018, 3:03pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/8 "2018-09-15T15:03:09Z")

</div>

Neither of those has anything to do with `const`. Const does not make a mutable object immutable, so there’s nothing wrong with modifying its field. It only requires that the binding (the label `foo`) is not reassigned to some other object.

The second case also has nothing to do with const, and you’ll get the same error without a const declaration. It’s simply a matter of trying to set a field with a value of the wrong type.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [September 15, 2018, 3:20pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/9 "2018-09-15T15:20:15Z")

</div>

`const` is regarding the constness of the _binding_, not the constness of the content in e.g. a container.

So if you have `const Foo = ...` it means you can never do `global Foo = something_else()`.

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 4:16pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/10 "2018-09-15T16:16:38Z")

</div>

Could this explanation go in the docs? As well as @rdeits’s comment about it being separate from mutability?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [September 15, 2018, 4:53pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/11 "2018-09-15T16:53:14Z")

</div>

The docs say

> Note that “constant-ness” does not extend into mutable containers; only the  
> association between a variable and its value is constant. If x is an array or  
> dictionary (for example) you can still modify, add, or remove elements.

But feel free to put up a PR with improved wording.

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 5:24pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/12 "2018-09-15T17:24:08Z")

</div>

Having thought about it, and considered the examples in this post, the explanation in the docs covers everything. I suppose I just had a mental block changing from c++ `const` to Julia `const`.

My tuppence on the subject that I expect that a lot of c++ focused developers will have raised eyebrows when the language even allows them to change something prefixed by `const` regardless of the warning. I for one would have better understood a word like `consttype` or `fixedtype`, or something entirely different like `strong`, to embody the qualities of `const`.

---

<div class="post-metadata">

**Author:** ![stabbles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stabbles/32/946_2.png) [@stabbles](https://discourse.julialang.org/u/stabbles)\
**Post date:** [September 15, 2018, 5:34pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/13 "2018-09-15T17:34:17Z")

</div>

Maybe compare it to the following in C++:

```nohighlight
struct Bar {
    int a;
};

struct Foo {
    Bar &a;
};

void f(Foo const &foo) {
    foo.a.a = 2;
}

```

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 15, 2018, 5:54pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/14 "2018-09-15T17:54:52Z")

</div>

I was totally wrong!

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [September 15, 2018, 6:26pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/15 "2018-09-15T18:26:13Z")

</div>

Yeah, I think it just comes down to the fact that C/C++ has two kinds of const-y pointers: a const pointer and a pointer-to-const, and they do completely different things: one stops you from changing what address the pointer points to and the other stops you from modifying whatever is at that address.

Julia handles things differently: mutability is a property of the object (`mutable struct` vs. `struct`), so the only thing a `const` annotation can do is inform the language that a particular binding will always refer to the same value. So Julia `const`s behave essentially like (I think…) const pointers, and not like pointers-to-const.

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 19, 2018, 2:16pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/16 "2018-09-19T14:16:07Z")

</div>

To follow on with the original issue here is a MWE of what I _now_ think is going on.

Needless to say I’ve been doing this kind of thing the type unstable way.

```julia
julia> struct Foo{T}
           bar::T
       end

julia> function unstable()
           foo = Foo(1)
           foos = Vector{Foo}([foo]) # what I've been doing
           f() = foos[1].bar
           return f
       end
unstable (generic function with 1 method)

julia> function stable()
           foo = Foo(1)
           foos = Vector{Foo{typeof(foo.bar)}}([foo]) # my guess work for stability
           f() = foos[1].bar
           return f
       end
stable (generic function with 1 method)

julia> f_stable = stable()
(::getfield(Main, Symbol("#f#4")){Array{Foo{Int64},1}}) (generic function with 1 method)

julia> f_unstable = unstable()
(::getfield(Main, Symbol("#f#3")){Array{Foo,1}}) (generic function with 1 method)

julia> @code_warntype f_stable()
Body::Int64
4 1 ─ %1 = (Core.getfield)(#self#, :foos)::Array{Foo{Int64},1} │ 
  │ %2 = (Base.arrayref)(true, %1, 1)::Foo{Int64} │╻ getindex
  │ %3 = (Base.getfield)(%2, :bar)::Int64 │╻ getproperty
  └── return %3 │ 

julia> @code_warntype f_unstable()
Body::Any
4 1 ─ %1 = (Core.getfield)(#self#, :foos)::Array{Foo,1} │ 
  │ %2 = (Base.arrayref)(true, %1, 1)::Foo │╻ getindex
  │ %3 = (Base.getfield)(%2, :bar)::Any │╻ getproperty
  └── return %3 │ 

```

Is creating `Vector{Foo{typeof(foo.bar)}}([foo])`, from `function stable()`, the only want get a type stability in the returned function?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [September 19, 2018, 3:00pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/17 "2018-09-19T15:00:23Z")

</div>

`Vector{Foo}` needs to be able to hold `Foo` with any `T` for example `[Foo(1), Foo(1.0), Foo("bar"), Foo([1,2,3])]`.

This is also possible

```julia
julia> function stable2()
           foo = Foo(1)
           foos = [foo] # what I've been doing
           f() = foos[1].bar
           return f
       end

```

---

<div class="post-metadata">

**Author:** ![jcook](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jcook/32/18211_2.png) [@jcook](https://discourse.julialang.org/u/jcook)\
**Post date:** [September 19, 2018, 5:48pm UTC](https://discourse.julialang.org/t/destroying-type-stabiliy-by-creating-chaining-closures-of-functions/14990/18 "2018-09-19T17:48:53Z")

</div>

Great! Thank you!
