# Help with error: "N not defined" in method signature but it is

**URL:** <https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226>\
**Category:** General Usage\
**Created:** [February 26, 2023, 3:50pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226 "2023-02-26T15:50:51Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [February 26, 2023, 3:50pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/1 "2023-02-26T15:50:51Z")

</div>

I understand this might not be idiomatic, but I would like to understand what’s going on here.

When compiling, the code below gives warning:

`WARNING: method definition for test at {File:Line} declares type variable N but does not use it.`

And when attempting to run it, it throws: `ERROR: UndefVarError: N not defined`

Could someone help me understand why the warning and error?

```julia
function test(x::Vector{T}, y)::NTuple{N,T} where {N,T}
    return (1,2,3)
end

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [February 26, 2023, 4:09pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/2 "2023-02-26T16:09:17Z")

</div>

Unlike `T`, `N` isn’t constrained by any type in the signature of your method, so it pretty much doesn’t exist: how can the assertion on the return type make sure you’re returning a `NTuple{N, T}` if `N` comes from nowhere?

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [February 26, 2023, 6:41pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/3 "2023-02-26T18:41:19Z")

</div>

@giordano 's answer is correct, but I didn’t understand it in the first reading. I think it’s clearer to mention that the compiler should be able to infer what type is `T` _through the input `x`_, but there is no input that clarifies what type should `N` be.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 26, 2023, 8:57pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/4 "2023-02-26T20:57:37Z")

</div>

> [@giordano](#):
>
> how can the assertion on the return type make sure you’re returning a `NTuple{N, T}` if `N` comes from nowhere?

idk, seems to work

```julia
julia> function test(x::Vector{T}, y) where T
           return (1,2,3)::NTuple{N,T} where N
       end
test (generic function with 1 method)

julia> test(Int[], ())
(1, 2, 3)

```

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 26, 2023, 9:36pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/5 "2023-02-26T21:36:44Z")

</div>

Okay, these seem to be the droids you’re looking for:

```julia
julia> function test(x::Vector{T}, y)::(NTuple{N,T} where N) where T
           return (1,2,3)
       end
test (generic function with 1 method)

julia> test(Int[], ())
(1, 2, 3)

```

Unlike the previous code, which simply performs type-assertion, this one does type-conversion.

```julia
julia> test(Float64[], ())
(1.0, 2.0, 3.0)

```

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [February 26, 2023, 9:47pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/6 "2023-02-26T21:47:29Z")

</div>

> [@uniment](#):
>
> idk, seems to work

You’re missing that the `N` _ **from the method signature** _ doesn’t exist, as the warning is telling you.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 26, 2023, 9:59pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/7 "2023-02-26T21:59:15Z")

</div>

> [@giordano](#):
>
> as the warning is telling you.

Hm, I don’t know that the warning has the right choice of wording.

```julia
julia> foo() where N = N
WARNING: method definition for foo at REPL[1]:1 declares type variable N but does not use it.
foo (generic function with 1 method)

julia> foo()
ERROR: UndefVarError: `N` not defined

```

seems like it would be better if the warning said something along the lines of

> [@giordano](#):
>
> `N` _ **from the method signature** _ doesn’t exist

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [February 26, 2023, 10:16pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/8 "2023-02-26T22:16:20Z")

</div>

Thank you all for the replies. The first response did answer why, but I realize I should have also asked “and what can I do about it?” I can’t just omit N, because NTuple requires something in that slot. I need a way to specify the type: “an NTuple of unknown length and elements of type T”. `NTuple{_,T}` doesn’t work. `NTuple{T}` doesn’t work.

It appears @uniment answered that with `(NTuple{N,T} where N)` which makes sense. I wasn’t familiar with using parentheses and multiple where clauses like that, so I’ll keep that in mind.

> [@](#):
>
> Unlike the previous code, which simply performs type-assertion, this one does type-conversion.

I don’t think there is any difference. If you look at the generated code, I think it always generates a call to convert when there is a return type specified.

```julia
function test2(::Type{T}, x)::T where T<:Number
	return 1
end
@code_lowered test2(Float64, 1)

CodeInfo(
1 ─ %1 = $(Expr(:static_parameter, 1))
│ %2 = Base.convert(%1, 1)
│ %3 = Core.typeassert(%2, %1)
└── return %3
)

```

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 26, 2023, 10:23pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/9 "2023-02-26T22:23:52Z")

</div>

> [@taotree](#):
>
> I don’t think there is any difference.

Observe:

```julia
julia> function bar(::Type{T}, x)::T where T; x end
       function baz(::Type{T}, x) where T; x::T end
baz (generic function with 1 method)

julia> bar(Float64, 1)
1.0

julia> baz(Float64, 1)
ERROR: TypeError: in typeassert, expected Float64, got a value of type Int64

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [February 26, 2023, 10:50pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/10 "2023-02-26T22:50:18Z")

</div>

> [@taotree](#):
>
> `NTuple{_,T}` doesn’t work. `NTuple{T}` doesn’t work.

What you’re looking for here is `NTuple{<:Any,T}`:

```julia
function test(x::Vector{T}, y)::NTuple{<:Any,T} where {T}
    return (1,2,3)
end

```

```julia
julia> test(Float64[], ())
(1.0, 2.0, 3.0)

```

---

<div class="post-metadata">

**Author:** ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)\
**Post date:** [February 26, 2023, 11:34pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/11 "2023-02-26T23:34:49Z")

</div>

> [@uniment](#):
>
> ```julia
> function baz(::Type{T}, x) where T; x::T end
> 
> ```

The error here is coming from the x::T, not the return of the method. Change it to:  
`function baz(::Type{T}, x) where T; x end`  
and it won’t give an error anymore.

---

<div class="post-metadata">

**Author:** ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)\
**Post date:** [February 26, 2023, 11:59pm UTC](https://discourse.julialang.org/t/help-with-error-n-not-defined-in-method-signature-but-it-is/95226/12 "2023-02-26T23:59:04Z")

</div>

> [@danielwe](#):
>
> What you’re looking for here is `NTuple{<:Any,T}`:

Although this works, this is (strictly speaking) an abuse of the type system: leveraging an undocumented implementation detail that `<:Any` currently simply doesn’t perform any typecheck on type parameters (after all, `3<:Any` throws an error, so it’s nonsensicle that `NTuple{3,Int}<:NTuple{<:Any,Int}` returns `true`). As such, when this loophole eventually gets fixed, your code will break.

See [this recent discussion](https://discourse.julialang.org/t/rfc-add-a-type-called-anytype-thats-subtyped-by-all-other-types-except-any/93956/11) for more.

> [@taotree](#):
>
> and it won’t give an error anymore.

It appears I mistook your intent then: I thought you intended to communicate that the element type of the function’s output tuple is constrained in accordance with the argument’s element type. If not, you could’ve always just written this:

```julia
function test(x::Vector, y)::NTuple
    return (1,2,3)
end

```
