# Dispatch on a set of value type parameters

**URL:** <https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864>\
**Category:** General Usage\
**Created:** [December 19, 2022, 4:54pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864 "2022-12-19T16:54:53Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [December 19, 2022, 4:54pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/1 "2022-12-19T16:54:53Z")

</div>

I have a type which has an `Int` value parameter, let’s represent the type like this:

```julia
struct T{m}
  some_fields
end

```

I want to define a method for a function `f` that takes a `T` value, but only if `m` is part of a certain finite set, for example if `m` is either `2`, `3` or `4`. However I also need access to `m` within the function.

This is the cleanest solution I could think of, however I wonder whether it’s possible to have `m` as a type parameter _within_ the `f` method:

```julia
m_val(::Type{T{m}}) where {m} = m

f(v::V) where {V <: Union{T{2}, T{3}, T{4}}} = 7*m_val(V)

```

Another possible solution would be to have a separate method for each value of `m`, which seems like it would be horrible due to code duplication.

---

<div class="post-metadata">

**Author:** ![RobertGregg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robertgregg/32/22105_2.png) [@RobertGregg](https://discourse.julialang.org/u/RobertGregg)\
**Post date:** [December 23, 2022, 10:40pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/2 "2022-12-23T22:40:43Z")

</div>

You may be able to play around with [Value types](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-value-type) but I think just adding `m` as a field simplifies things. You can keep the Int Type if you want for other methods. For example:

```julia
struct newType{M}
    m::Int
    A::Array{Int,M} #just some random field that depends on m (M==m)

    function newType(M)
        A = zeros(Int, ntuple(x->3,M)) #each axis has length 3
        new{M}(M,A)
    end
end

```

Now you can create a function that takes in any version of the type and use `m`:

```julia
f(v::newType, finiteSet) = v.m ∈ finiteSet ? 7v.m : error("m not in set")

```

If we make some instances of `newType` we can test `f`:

```julia
julia> v3 = newType(3);

julia> v8 = newType(8);

julia> typeof(v3)
newType{3}

julia> typeof(v8)
newType{8}

julia> finiteSet = [2,3,4];

julia> f(v3,finiteSet)
21

julia> f(v8,finiteSet)
ERROR: m not in set

```

I’m not an expert on types so this might be bad advice 🤷 but it avoids code duplication and works for any `m`.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [December 23, 2022, 11:09pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/3 "2022-12-23T23:09:38Z")

</div>

Maybe I should have said this explicitly when asking the question, but the point of using compile-time dispatch is performance. Your solution wouldn’t have cut it because `f` was supposed to be called within hot loops.

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [December 23, 2022, 11:10pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/4 "2022-12-23T23:10:55Z")

</div>

The solution would be to use `StaticNumbers` and include `m` as a field in `struct T` something like this:

```julia
struct T{m}
  some_fields
  mm::StaticInteger{m}
end

```

Note:

```plaintext
julia> Base.issingletontype(StaticInteger{3})
true

```

---

<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:** [December 23, 2022, 11:23pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/5 "2022-12-23T23:23:50Z")

</div>

It seems like you’re already in good shape, and you’re just looking for ways to avoid polluting the global namespace with a new function that’s specific to `f`.

You can achieve this by declaring a local function:

```julia
julia> struct T{m} end

julia> f(v::V) where {V<:Union{T{2},T{3},T{4}}} =
           let mval(::Type{T{m}}) where {m} = m
               7*mval(V)
           end

julia> f(T{2}())
14

```

Another approach would be to access the property directly:

```julia
julia> f(v::V) where {V<:Union{T{2},T{3},T{4}}} = 7*V.parameters[1]
f (generic function with 1 method)

julia> f(T{2}())
14

```

but this isn’t Julian. I don’t know of any method for accessing a type’s parameters; it’d be nice if we had `parametersof(::Type{T}) where T = Tuple(T.parameters)` but we don’t.

> [@nsajko](#):
>
> use `StaticNumbers` and include `m` as a field in `struct T`

Hm this library is pretty cool. This looks like a good solution too.

---

<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:** [December 23, 2022, 11:56pm UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/6 "2022-12-23T23:56:58Z")

</div>

Also, if you want a more programmatic solution, you can use the `@generated` macro to produce different function body expressions depending on the argument types:

```julia
julia> @generated f(v::T{m}) where m = let
           if m ∈ (2, 3, 4) quote 7*$m end
           else quote throw(string($m)*" not supported") end
           end
       end
f (generic function with 1 method)

julia> f(T{1}())
ERROR: "1 not supported"

julia> f(T{2}())
14

```

---

<div class="post-metadata">

**Author:** ![RobertGregg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/robertgregg/32/22105_2.png) [@RobertGregg](https://discourse.julialang.org/u/RobertGregg)\
**Post date:** [December 24, 2022, 12:20am UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/7 "2022-12-24T00:20:16Z")

</div>

Ah makes sense. I’ll also have to look at `StaticNumbers` as well. I’m curious what the application is for this setup?

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [December 24, 2022, 3:21am UTC](https://discourse.julialang.org/t/dispatch-on-a-set-of-value-type-parameters/91864/8 "2022-12-24T03:21:47Z")

</div>

> [@RobertGregg](#):
>
> I’m curious what the application is for this setup?

My goal (since abandoned because of various reasons) was to write an iterator that is a Cartesian power of another, wrapped, iterator. So basically a special case of the Cartesian product iterator from `Base.Iterators`.

So instead of

```julia
struct T{m}
  some_fields
end

```

I had something like this:

```julia
struct PowerIterator{m, It <: Any}
  wrapped_iterator::It
end

```

and I asked the question while trying to write specialized implementations for `Base.iterate` for a few small `m`, where `m` is the exponent in the Cartesian power.
