# Why doesn't this function compile

**URL:** <https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665>\
**Category:** General Usage\
**Created:** [July 2, 2022, 3:13pm UTC](https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665 "2022-07-02T15:13:23Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![atteson](https://avatars.discourse-cdn.com/v4/letter/a/91b2a8/32.png) [@atteson](https://discourse.julialang.org/u/atteson)\
**Post date:** [July 2, 2022, 3:13pm UTC](https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665/1 "2022-07-02T15:13:23Z")

</div>

Can anyone tell me why this code doesn’t compile:

```julia
function f1( x::T ) where {T}
    function f2( y::U ) where {U <: AbstractVector{T}}
        return 0.0
    end
    return f2
end

```

---

<div class="post-metadata">

**Author:** ![aramirezreyes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aramirezreyes/32/42573_2.png) [@aramirezreyes](https://discourse.julialang.org/u/aramirezreyes)\
**Post date:** [July 2, 2022, 4:04pm UTC](https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665/2 "2022-07-02T16:04:47Z")

</div>

> [@atteson](#):
>
> ```julia
> function f1( x::T ) where {T}
> function f2( y::U ) where {U <: AbstractVector{T}}
> return 0.0
> end
> return f2
> end
> 
> ```

I think you also need to parameterize the T inside:

```julia
julia> function f1( x::T ) where {T}
           function f2( y::U ) where {U <: AbstractVector{T}} where T
               return 0.0
           end
           return f2
       end
f1 (generic function with 1 method)

```

---

<div class="post-metadata">

**Author:** ![brianguenter](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brianguenter/32/29519_2.png) [@brianguenter](https://discourse.julialang.org/u/brianguenter)\
**Post date:** [July 2, 2022, 5:11pm UTC](https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665/3 "2022-07-02T17:11:15Z")

</div>

It depends on what @atteson was hoping to accomplish. I read the code as an attempt to force the element type of the `AbstractVector y` to be the same as the type of the argument passed into `f1`.

_If_ that was the intent then adding the second `where T` won’t work since T gets bound to a different type in f2:

```julia
julia> function f1( x::T ) where {T}
                  function f2( y::U ) where {U <: AbstractVector{T}} where T
                                 return 0.0
                  end
                  return f2
              end
f1 (generic function with 1 method)

julia> a = f1(1.0)
(::var"#f2#12") (generic function with 1 method)

julia> a(["this","that"])
0.0 

```

This alternative forces the element type of `y` to be the same as the type of the argument to f1:

```julia
julia> function f1(x::T ) where {T}
           function f2(y::AbstractVector{T})
               return 0.0
           end
           return f2
       end
f1 (generic function with 1 method)

julia> a = f1(1.0)
(::var"#f2#11"{Float64}) (generic function with 1 method)

julia> a([1.0,2.0])
0.0

julia> a([1,2])
ERROR: MethodError: no method matching (::var"#f2#11"{Float64})(::Vector{Int64})
Closest candidates are:
  (::var"#f2#11"{T})(::AbstractVector{T}) where T at REPL[24]:2
Stacktrace:
 [1] top-level scope
   @ REPL[27]:clock130: 

```

---

<div class="post-metadata">

**Author:** ![atteson](https://avatars.discourse-cdn.com/v4/letter/a/91b2a8/32.png) [@atteson](https://discourse.julialang.org/u/atteson)\
**Post date:** [July 2, 2022, 7:30pm UTC](https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665/4 "2022-07-02T19:30:42Z")

</div>

Thank you. That is my intention. Let me change the problem to why the following doesn’t compile. In this case, doing what you suggest would, in my experience, lead to potential type instability since the code wouldn’t be compiled for each possible type of of AbstractVector{T}.

```julia
function f1( x::T ) where {T}
    function f2( y::AbstractVector{U} ) where {U <: AbstractVector{T}}
        return 0.0
    end
    return f2
end

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [July 2, 2022, 9:20pm UTC](https://discourse.julialang.org/t/why-doesnt-this-function-compile/83665/5 "2022-07-02T21:20:05Z")

</div>

What failed is the method definition, not compilation (which happens upon function call).

You should also know that in Julia, nested methods like `f2` aren’t defined each time outer methods like `f1` are called. They’re both defined at the same time, it’s more like the inner one is also implemented with a hidden struct is instantiated at each call of `f1` to “capture” `f1` variables, look up “functors” in the docs. However, captured variables must be in the method _body_, not the header type annotations, hence your original `UndefVarError: T not defined` for `f2`.

This however is perfectly legal and doesn’t need to be nested to capture any variables at all. Think of `f3`’s T as a variable that is inferred from the argument `y` at method call, and `f3` _is_ compiled for every type of `T` (and `U`).

```julia
julia> function f3( y::AbstractVector{U} ) where {T, U <: AbstractVector{T}}
         return T, U, typeof(y)
       end

```

`where {T, U <: AbstractVector{T}}` is equivalent to `where {U <: AbstractVector{T}} where T`, so like @brianguenter said, adding the extra `where T` to `f2` actually does the same thing as `f3`, meaning the `T` for `f2` is different from the `T` for `f1`.
