# Weird type errors when manipulating arrays of functions

**URL:** https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709
**Category:** General Usage
**Created:** [October 23, 2018, 10:43pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709 "2018-10-23T22:43:23Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![jonathan-laurent](https://avatars.discourse-cdn.com/v4/letter/j/ecae2f/32.png) [@jonathan-laurent](https://discourse.julialang.org/u/jonathan-laurent)
#### Post date: [October 23, 2018, 10:43pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/1 "2018-10-23T22:43:23Z")

</div>

Here are four expressions that I expect to evaluate to `[sin, sin ∘ sin]`:

```julia
accumulate(∘, [sin, sin]) #1
accumulate(∘, [x -> sin(x), x -> sin(x)]) #2
accumulate(∘, [sin for i=1:2]) #3
accumulate(∘, [x -> sin(x) for i=1:2]) #4

```

However, only the second version is accepted by Julia. For the others, I get the following cryptic errors:

```julia
julia> accumulate(∘, [sin, sin]) #1
ERROR: MethodError: Cannot `convert` an object of type typeof(sin) to an object of type getfield(Base, Symbol("##52#53")){typeof(sin),typeof(sin)}

```

```julia
julia> accumulate(∘, [sin for i=1:2]) #3
ERROR: MethodError: Cannot `convert` an object of type typeof(sin) to an object of type getfield(Base, Symbol("##52#53")){typeof(sin),typeof(sin)}

```

```julia
julia> accumulate(∘, [x -> sin(x) for i=1:2]) #4
ERROR: MethodError: Cannot `convert` an object of type getfield(Main, Symbol("##100#102")) to an object of type getfield(Base, Symbol("##52#53")){getfield(Main, Symbol("##100#102")),getfield(Main, Symbol("##100#102"))}

```

Does anyone have a clue what’s happening here?

---

<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: [October 23, 2018, 10:47pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/2 "2018-10-23T22:47:16Z")

</div>

If I remember correctly, accumulate has some difficulties in determining the proper return type, so it’s constructing an overly narrow array as the result and then having trouble assigning the differently-typed function into slot 2. Simon Byrne has a PR that should fix it.

All four work if you use `Any[…]` or `Function[…]` arrays as input — #2 is the already the latter.

---

<div class="post-metadata">

### Author: ![jonathan-laurent](https://avatars.discourse-cdn.com/v4/letter/j/ecae2f/32.png) [@jonathan-laurent](https://discourse.julialang.org/u/jonathan-laurent)
#### Post date: [October 23, 2018, 11:41pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/3 "2018-10-23T23:41:15Z")

</div>

Thanks a lot!

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [October 24, 2018, 5:48am UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/4 "2018-10-24T05:48:49Z")

</div>

> [@jonathan-laurent](#):
>
> cryptic errors

Also, the `getfield(...)` is a closure.

I guess its printing could be improved, but could not find an issue, is there one?

---

<div class="post-metadata">

### Author: ![jonathan-laurent](https://avatars.discourse-cdn.com/v4/letter/j/ecae2f/32.png) [@jonathan-laurent](https://discourse.julialang.org/u/jonathan-laurent)
#### Post date: [October 24, 2018, 2:47pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/5 "2018-10-24T14:47:46Z")

</div>

> [@Tamas\_Papp](#):
>
> I guess its printing could be improved, but could not find an issue, is there one?

As a new user of Julia coming from a functional programming background, I find several things surprising here. I do not have enough experience to judge whether or not they should be regarded as _issues_ though.

First, why would closures be treated any differently than standard functions by the _type system_?

Then, why aren’t closure types stable under composition? For example:

```julia
julia> typeof(x -> x+1)
getfield(Main, Symbol("##33#34"))

```

```julia
julia> typeof((x -> x+1) ∘ (x -> x+1))
getfield(Base, Symbol("##52#53")){getfield(Main, Symbol("##39#41")),getfield(Main, Symbol("##40#42"))}

```

I could get an arbitrarily long type by composing more closures together.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [October 24, 2018, 3:42pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/6 "2018-10-24T15:42:25Z")

</div>

> [@jonathan-laurent](#):
>
> First, why would closures be treated any differently than standard functions by the _type system_ ?

I don’t think they are treated differently. You may want to read the development docs, [eg the chapter on functions](https://docs.julialang.org/en/stable/devdocs/functions/).

> [@jonathan-laurent](#):
>
> why aren’t closure types stable under composition?

Because they generally aren’t? Eg

```julia
julia> c = x -> x isa Char ? x - 'a' : x + 'a'
#35 (generic function with 1 method)

julia> c('b')
1

julia> (c∘c)('b')
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)

```

---

<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: [October 24, 2018, 4:32pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/7 "2018-10-24T16:32:33Z")

</div>

Every generic function has its own type. Since Julia does type-based inference and specialization, this is precisely what makes higher order functions fast. It means that Julia can reason about the return types of functions that get passed as arguments (and a whole host of other optimizations). This wasn’t always the case… and changing it to be this way was a HUGE improvement!

---

<div class="post-metadata">

### Author: ![jonathan-laurent](https://avatars.discourse-cdn.com/v4/letter/j/ecae2f/32.png) [@jonathan-laurent](https://discourse.julialang.org/u/jonathan-laurent)
#### Post date: [October 24, 2018, 4:34pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/8 "2018-10-24T16:34:26Z")

</div>

@Tamas_Papp To me, one sign of closures and functions being treated differently by the type system is that the two following lines are not equivalent:

```julia
accumulate(∘, [sin, sin]) # Type error
accumulate(∘, [x -> sin(x), x -> sin(x)]) # Ok

```

Also, I should have been more precise when I said that I expected “the type of closures to be stable under composition”. I referred to the specific case where the closure has one argument and where its input and output types coincide.

**Edit** : @mbauman answered my question.

---

<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: [October 24, 2018, 4:40pm UTC](https://discourse.julialang.org/t/weird-type-errors-when-manipulating-arrays-of-functions/16709/9 "2018-10-24T16:40:57Z")

</div>

A bit more directly, `[sin, sin]` is an array that can only hold `typeof(sin)` objects:

```julia
julia> A = [sin, sin]
2-element Array{typeof(sin),1}:
 sin
 sin

julia> A[1] = cos
ERROR: MethodError: Cannot `convert` an object of type typeof(cos) to an object of type typeof(sin)

julia> A[1] = x->sin(x)
ERROR: MethodError: Cannot `convert` an object of type getfield(Main, Symbol("##24#25")) to an object of type typeof(sin)

```

The array `[x->sin(x), x->sin(x)]` is actually holding onto two _different_ functions; the two anonymous functions are not the same, so they have different types, so constructing an array with them chooses the narrowest common supertype: `Function`:

```julia
julia> B = [x->sin(x), x->sin(x)]
2-element Array{Function,1}:
 getfield(Main, Symbol("##30#32"))()
 getfield(Main, Symbol("##31#33"))()

julia> B[1] == B[2]
false

julia> B[1] = cos
cos (generic function with 12 methods)

julia> B
2-element Array{Function,1}:
 cos
 getfield(Main, Symbol("##31#33"))()

```

Were you to construct this such that you have the same anonymous function, it’ll behave like `A`:

```julia
julia> g = x->sin(x); C = [g, g]
2-element Array{getfield(Main, Symbol("##34#35")),1}:
 getfield(Main, Symbol("##34#35"))()
 getfield(Main, Symbol("##34#35"))()

julia> C[1] = sin
ERROR: MethodError: Cannot `convert` an object of type typeof(sin) to an object of type getfield(Main, Symbol("##34#35"))

```
