# Test for a zero-valued Tuple in where statement

**URL:** https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579
**Category:** General Usage
**Tags:** dispatch, val
**Created:** [April 17, 2023, 3:23pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579 "2023-04-17T15:23:42Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [April 17, 2023, 3:23pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/1 "2023-04-17T15:23:42Z")

</div>

I would like to have a special dispatch for the case that a Tuple{} in the type definition is zero (in all entries). For example:

```julia
foo(a::AbstractArray{T, N}) where {N, T<:Tuple{zeros(Int,N)...}}

```

but get an error since `N` when used inside the where statement is of type `::TypeVar`.  
Is there a way to convert this into a value?  
I also tried

```julia
foo(a::AbstractArray{T, N}) where {N, T<:Tuple{zeros(Int,Val(N))...}} = a

```

which gives a somewhat strange error:

```julia
ERROR: UndefVarError: x not defined
Stacktrace:
 [1] Val{N}()
   @ Base .\essentials.jl:712
 [2] Val(x::TypeVar)
   @ Base .\essentials.jl:714
 [3] top-level scope
   @ REPL[91]:1

```

Note that

```julia
foo(a::AbstractArray{T,N}) where {N,T<:Tuple{zeros(Int,3)...}} = a

```

works just fine.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [April 17, 2023, 6:34pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/2 "2023-04-17T18:34:18Z")

</div>

> [@RainerHeintzmann](#):
>
> which gives a somewhat strange error:

More notably is that this crashed with segmentation fault Julia 1.9 (bug filled [here](https://github.com/JuliaLang/julia/issues/49390)).

Concerning your question: I don’t think you can do that. If you really need that behavior you probably need to wrap the tuple in a custom struct that is type-parameterized for that specifically.

---

<div class="post-metadata">

### Author: ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)
#### Post date: [April 17, 2023, 8:30pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/4 "2023-04-17T20:30:13Z")

</div>

Here is what I don’t understand: I don’t see how you can make the simplified example

```julia
foo(a::AbstractArray{T,1}) where {T<:Tuple{zeros(Int,1)...}} = a

@show foo(Tuple{0}[]) # works
@show foo(Tuple{0}[()]) # fails with
# MethodError: Cannot `convert` an object of type
# Tuple{} to an object of type
# Tuple{0}

```

(which _compiles_) make to work for a non empty vectors. Ideas anyone?

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [April 17, 2023, 8:50pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/5 "2023-04-17T20:50:58Z")

</div>

`Tuple{0}` is a “valid” type just like `Array{1.2,3//4}` is a “valid” type. `0`, `1.2`, and `3//4` are all `isbits` so are valid type parameters. This does not mean they actually result in “well-formed” types.

So while you can instantiate an array via `Tuple{0}[]` or `Array{Tuple{0}}(undef,n)`, there is literally no element that you can insert into them because there are no instances of a `Tuple{0}` that can exist.

You can have a value `(0,0)` with `typeof((0,0)) == Tuple{Int,Int}`, however, which is probably closer to what you’re actually dealing with. Notice the parentheses `()` for values and braces `{}` for types.

* * *

To the original question: you cannot check for a _value_ (including zero) at the type level. You can create `Val{0}()`, which is a value of type `Val{0}`, but that will not help you here and `Val`s aren’t useful for much except dispatch. It’s a bit unclear exactly what is being asked because it’s unclear where types versus values are intended.

You can write

```julia
foo(a::AbstractArray{<:Tuple{Vararg{Any,N}},N}) where N = all(Base.Fix1(all,iszero), a) ? foo_if_all_zero(a) : foo_else(a)

# or, if you don't care about the length of the tuple versus the dimension of the array
foo(a::AbstractArray{<:Tuple}) = all(Base.Fix1(all, iszero), a) ? foo_if_all_zero(a) : foo_else(a)

```

and proceed to define the `foo_if_all_zero` and `foo_else` function specifically. But it’s unclear if this is what you’re after. Why should the length of the tuple match the dimension of the array?

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [April 17, 2023, 9:02pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/6 "2023-04-17T21:02:59Z")

</div>

What are you trying to dispatch on?

It sounds like you mean to dispatch for

```julia
julia> t = (0, 0, 0, 0)
(0, 0, 0, 0)

julia> typeof(t)
NTuple{4, Int64}

julia> Tuple{Int, Int, Int, Int} == NTuple{4, Int}
true

```

As shown above the type of `t` is `NTuple{4, Int64}`, not `NTuple{4, Val{0}}`. For that we would need the following.

```julia
julia> t2 = Val.((0,0,0,0))
(Val{0}(), Val{0}(), Val{0}(), Val{0}())

julia> typeof(t2)
NTuple{4, Val{0}}

```

Then we could do dispatch as follows.

```julia
julia> foo(a::AbstractArray{T,N}) where {N, T <: NTuple{N,Val{0}}} = 5
foo (generic function with 1 method)

julia> foo([t2 ;;;;])
5

```

If you wanted a more flexible version where `T` could be an `NTuple` with any number of `Val(0)`, you could do

```julia
julia> foo(a::AbstractArray{T,N}) where {N, N2, T <: NTuple{N2,Val{0}}} = N2
foo (generic function with 2 methods)

julia> foo([Val.((0,)) ;;;;])
1

julia> foo([Val.((0,0)) ;;;;])
2

julia> foo([Val.((0,0,0)) ;;;;])
3

```

However, my suspicion is that you really want to dispatch on something like `(0,0,0,0)`. We can do this with two definitions. The first checks the array to make sure it consists of tuples of a single value.

```julia
julia> foo(a::AbstractArray{T,N}) where {N, T <: NTuple{N}} = foo(a, Val(only(unique(only(unique(a))))))
foo (generic function with 4 methods)

julia> foo(a::AbstractArray{T,N}, ::Val{0}) where {N, T <: NTuple{N}} = println("This $(N)D array is filled with $N-Tuples filled with zeros")
foo (generic function with 4 methods)

julia> foo([(0,)])
This 1D array is filled with 1-Tuples filled with zeros

julia> foo([(0,0) ;;])
This 2D array is filled with 2-Tuples filled with zeros

julia> foo([(0,0,0) ;;;])
This 3D array is filled with 3-Tuples filled with zeros

julia> foo([(0,0,0,0) ;;;;])
This 4D array is filled with 4-Tuples filled with zeros

julia> foo([(0,0,0) ;;;;])
ERROR: MethodError: no method matching foo(::Array{Tuple{Int64, Int64, Int64}, 4})

julia> foo([(0,0,0,1) ;;;;])
ERROR: ArgumentError: Collection has multiple elements, must contain exactly 1 element

julia> foo([(1,1,1,1) ;;;;])
ERROR: MethodError: no method matching foo(::Array{NTuple{4, Int64}, 4}, ::Val{1})

```

Honestly though, you probably should just write an `if` statement rather than using multiple dispatch to do this.

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [April 17, 2023, 9:08pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/7 "2023-04-17T21:08:00Z")

</div>

> [@RainerHeintzmann](#):
>
> `foo(a::AbstractArray{T, N}) where {N, T<:Tuple{zeros(Int,Val(N))...}} = a`

I just found a possible solution, which seems pretty much a simplified version of your Vararg suggestion

```julia
foo(a::AbstractArray{T, N}) where {N, T<:NTuple{N,0}} = a

```

I think this should do.  
The point really is that I would like to treat a CircShiftedArray with shift zero at the compiler-level as an ordinary array, to speed up things. So the compiler should be able to figure out that there is a part of the type signature having the Shfit: `Tuple{0,0,0}`.

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [April 17, 2023, 9:16pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/8 "2023-04-17T21:16:16Z")

</div>

> [@RainerHeintzmann](#):
>
> `foo(a::AbstractArray{T, N}) where {N, T<:NTuple{N,0}}`

There is no value of type `NTuple{N, 0} where N`. Thus, the array type you’re after can only ever be empty so isn’t very interesting. You are trying to identify the _value_ `(0,0,0)` which has type `NTuple{3,Int}`. But the value `(1,2,-3)` also has this same type. You cannot distinguish among them via dispatch.

Honestly, I don’t expect a massive gain from using the special case of a zero offset. I’d start without it. You can make an `if all(iszero, offsets)` (where offsets is a value of type `NTuple{N,Int}`) branch to handle this special case inside your function (or have it call a different function) if you do find it to be a useful optimization.

---

<div class="post-metadata">

### Author: ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)
#### Post date: [April 17, 2023, 9:20pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/9 "2023-04-17T21:20:12Z")

</div>

Sorry for bothering you: my adapted test is

```julia
foo(a::AbstractArray{T, 1}) where {T<:NTuple{1,0}} = a

@show foo(NTuple{1, 0}[]) # works
@show foo(NTuple{1, 0}[()]) # fails with
# MethodError: Cannot `convert` an object of type
# Tuple{} to an object of type
# Tuple{0}

```

and I’m still failing to see how to create a non empty vector here. Could you show us how to do this, please?

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [April 17, 2023, 9:22pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/10 "2023-04-17T21:22:29Z")

</div>

> [@RainerHeintzmann](#):
>
> `foo(a::AbstractArray{T, N}) where {N, T<:NTuple{N,0}} = a`

Sorry, I think the “simplified example” I was trying to make up was a bit over-simplified.  
Here is the code which I put in the package:

```julia
split_array_broadcast(bc::CircShiftedArray{N,S}, noshift_rng, shift_rng) where {N,S<:NTuple{M,0}} where {M}= @view bc.parent[noshift_rng...]

```

It is supposed to be triggered for example for `a::CircShiftArray{2,Tuple{0,0}}` but not for `a::CircShiftArray{2,Tuple{0,1}}`.  
Does this make sense now?

---

<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: [April 17, 2023, 9:24pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/11 "2023-04-17T21:24:25Z")

</div>

> [@RainerHeintzmann](#):
>
> It is supposed to be triggered for example for `a::CircShiftArray{2,Tuple{0,0}}` but not for `a::CircShiftArray{2,Tuple{0,1}}`

Have you managed to make a instance of `CircShiftArray{2,Tuple{0,0}}` with \>0 elements yet? If so, please provide example code for that and a function call for `split_array_broadcast`.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [April 17, 2023, 9:24pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/12 "2023-04-17T21:24:46Z")

</div>

> [@RainerHeintzmann](#):
>
> ```julia
> foo(a::AbstractArray{T, N}) where {N, T<:NTuple{N,0}} = a
> 
> ```
> 
> I think this should do.  
> The point really is that I would like to treat a CircShiftedArray with shift zero at the compiler-level as an ordinary array, to speed up things. So the compiler should be able to figure out that there is a part of the type signature having the Shfit: `Tuple{0,0,0}`.

This does not work. There is no way to create an instance of `Tuple{0,0,0}`.

```julia
julia> (0,0,0) isa Tuple{0,0,0}
false

```

You can do one of these.

```julia
julia> (Val(0),Val(0),Val(0)) isa Tuple{Val{0},Val{0},Val{0}}
true

julia> Val((0,0,0)) isa Val{(0,0,0)}
true

```

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [April 17, 2023, 9:28pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/13 "2023-04-17T21:28:39Z")

</div>

Okay. If you’re using the _type_ `Tuple{X,Y}` to hardcode the offsets then you can get away with this. `StaticArrays.jl` uses this same technique to store array sizes in the type domain. I believe what you wrote (`NTuple{N,0} where N`) will work for your purposes, i.e., identifying the type or type parameter `Tuple{0,0,...}` (of which no instance can exist, but the type itself is valid).

I still have some skepticism that this provides a significant performance benefit over just holding the offset as a value of type `NTuple{N,Int}`. But that comes down to how much one considers “significant” and the amount of extra code they’re willing to produce. If your offsets are not known at compile time, this will perform much worse than a value-based solution because it will necessitate dynamic dispatch. It will also result in a separate function being compiled for each unique offset, which may quickly get out of hand.

---

<div class="post-metadata">

### Author: ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)
#### Post date: [April 17, 2023, 9:41pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/14 "2023-04-17T21:41:59Z")

</div>

You can simplify further as follows.

```julia
julia> bar(a::CircShiftedArray{N,NTuple{N,0}}) where N = 1
bar (generic function with 1 methods)

julia> bar(a::CircShiftedArray{N,<: Tuple}) where N = 0
bar (generic function with 2 methods)

julia> bar(CircShiftedArray{2,Tuple{0,1}}())
0

julia> bar(CircShiftedArray{2,Tuple{0,0}}())
1

```

---

<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: [April 17, 2023, 9:45pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/15 "2023-04-17T21:45:22Z")

</div>

> [@mikmoore](#):
>
> `Tuple{X,Y}` to hardcode the offsets then you can get away with this. `StaticArrays.jl` uses this same technique to store array sizes in the type domain.

Now I think about it, why _is_ `Tuple{size_tuple...}` used there instead of `Val{size_tuple}`?

---

<div class="post-metadata">

### Author: ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)
#### Post date: [April 17, 2023, 9:51pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/16 "2023-04-17T21:51:59Z")

</div>

Great. Thanks mkitti for the suggestion. Works nicely.

---

<div class="post-metadata">

### Author: ![mikmoore](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mikmoore/32/31109_2.png) [@mikmoore](https://discourse.julialang.org/u/mikmoore)
#### Post date: [April 17, 2023, 9:52pm UTC](https://discourse.julialang.org/t/test-for-a-zero-valued-tuple-in-where-statement/97579/17 "2023-04-17T21:52:14Z")

</div>

> [@Benny](#):
>
> Now I think about it, why _is_ `Tuple{size_tuple...}` used there instead of `Val{size_tuple}`?

This is above my pay grade, but I’m guessing so that they can do things like this

```julia
julia> Tuple{1,2} <: Tuple{1,N} where N
true

julia> Val{(1,2)} <: Val{(1,N)} where N
ERROR: TypeError: in Type, in parameter, expected Type, got a value of type Tuple{Int64, TypeVar}

```

Obviously that _specific_ pattern probably never appears, but I’m sure there are cases where something like it is useful.
