# Understanding specialization and parametric types

**URL:** <https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680>\
**Category:** New to Julia\
**Tags:** question, parametric-types\
**Created:** [October 9, 2019, 12:36pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680 "2019-10-09T12:36:14Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![rapus95](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapus95/32/3773_2.png) [@rapus95](https://discourse.julialang.org/u/rapus95)\
**Post date:** [October 9, 2019, 12:36pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/1 "2019-10-09T12:36:14Z")

</div>

EDITSTART  
The following link @Tamas_Papp posted in the solution might help everyone with similar questions.  
[https://docs.julialang.org/en/v1/manual/methods/#Design-Patterns-with-Parametric-Methods-1](https://docs.julialang.org/en/v1/manual/methods/#Design-Patterns-with-Parametric-Methods-1)  
EDITEND

Right now I try to understand how specialization and parametric types interact. The following all came up when trying to design a sliding window iterator (iterator that shall return a slided view of an array in each iteration step)  
Code so far, not yet working as we are missing an iterate function etc:

```julia
using IdentityRanges

struct SlidingWindowIterator #1
    array::AbstractArray #2
    range::CartesianIndices #3
    validindices::CartesianIndices #3
end

```

#3 is the set of indices of `array` that have all needed indices for`range` as valid indices around them.

Objectives: Make it specialize for the array type and the dimension (Are there other attributes that should be parametrized for performance reasons?). Also enforce all 3 arguments to be of the same dimension. And have a constructor that fills in all parameter types automatically. How to do that?

---

<div class="post-metadata">

**Author:** ![yurivish](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yurivish/32/307_2.png) [@yurivish](https://discourse.julialang.org/u/yurivish)\
**Post date:** [October 9, 2019, 12:53pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/2 "2019-10-09T12:53:24Z")

</div>

I think something like this is what you’re after:

```julia
struct SlidingWindowIterator{T<:AbstractArray} #1
    array::T #2
    range::CartesianIndices #3
    validindices::CartesianIndices #3
    function SlidingWindowIterator(array::T, range, validindices) where T <: AbstractArray
        if false # do your validation here
            error("invalid indices")
        end
        return new{T}(array, range, validindices)
    end
end

```

By parameterizing the type on the specific type of `AbstractArray` that `array` is, you define a family of types, each with a storage layout optimized for the specific array type that gets passed in.

The function inside the struct definition is an inner constructor, which becomes the only way to construct the type. You can perform any needed validation there.

Actually, you should also specialize the types of the indices, since `CartesianIndices` is also an abstract type. Here I gave both index ranges the same type, since they’re both supposed to be indices for the same array:

```julia
struct SlidingWindowIteratorTwo{T<:AbstractArray, I<:CartesianIndices} #1
    array::T #2
    range::I #3
    validindices::I #3
    function SlidingWindowIteratorTwo(array::T, range::I, validindices::I) where {T <: AbstractArray, I <: CartesianIndices}
        if false # do your validation here
            error("invalid indices")
        end
        return new{T, I}(array, range, validindices)
    end
end

```

---

<div class="post-metadata">

**Author:** ![rapus95](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapus95/32/3773_2.png) [@rapus95](https://discourse.julialang.org/u/rapus95)\
**Post date:** [October 9, 2019, 1:08pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/3 "2019-10-09T13:08:42Z")

</div>

Assuming that I can collect the iteration values after collapsing each window into a single value, the `validindices` field will become the indices of the newly collected array. Thus they probably need to support non-1-based indexing. Likewise for `range`. Thus I will probably need different types for them.

Now, I need access to the dimensions of the `array` in order to implement the

```julia
Base.IteratorSize(::Type{SlidingWindowIterator}) = HasShape{N} #6

```

How can I solve that best?

---

<div class="post-metadata">

**Author:** ![rapus95](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapus95/32/3773_2.png) [@rapus95](https://discourse.julialang.org/u/rapus95)\
**Post date:** [October 9, 2019, 3:04pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/4 "2019-10-09T15:04:45Z")

</div>

I now did it that way:

```julia
Base.IteratorSize(::Type{SlidingWindowIterator{AT,A,B}}) where {T,N,AT<:AbstractArray{T,N},A,B} = Base.HasShape{N}() #6

```

Ist there any possibility to somehow prevent specialization on T, A and B? Or maybe even to not list them. Something like `{AT,_,_}` would be cool

---

<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 9, 2019, 4:43pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/5 "2019-10-09T16:43:53Z")

</div>

> [@rapus95](#):
>
> Base.IteratorSize(::Type{SlidingWindowIterator{AT,A,B}})

If you don’t need the type parameters, you can just do

```julia
Base.IteratorSize(::Type{<:SlidingWindowIterator}) = ...

```

---

<div class="post-metadata">

**Author:** ![rapus95](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapus95/32/3773_2.png) [@rapus95](https://discourse.julialang.org/u/rapus95)\
**Post date:** [October 10, 2019, 5:54am UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/6 "2019-10-10T05:54:43Z")

</div>

I need the AT parameter because I need the N parameter for the dimension. Is there a better solution that doesn’t force me to have 5 type parameters (some of them nested) to use a single type parameter? Maybe even preventing to specialize on unneeded type params.

---

<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 10, 2019, 5:57am UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/7 "2019-10-10T05:57:41Z")

</div>

If you just need the `N` from the `AT`, you can do

```julia
Base.IteratorSize(::Type{<:SlidingWindowIterator{AT}}) = somehow_use(ndims(AT))

```

---

<div class="post-metadata">

**Author:** ![rapus95](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapus95/32/3773_2.png) [@rapus95](https://discourse.julialang.org/u/rapus95)\
**Post date:** [October 10, 2019, 5:59am UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/8 "2019-10-10T05:59:04Z")

</div>

Like that?:

```julia
Base.IteratorSize(::Type{<:SlidingWindowIterator{AT}}) where AT = Base.HasShape{ndims(AT)}()

```

or that

```julia
Base.IteratorSize(::Type{<:SlidingWindowIterator{AT}}) where {AT<:AbstractArray} = Base.HasShape{ndims(AT)}()

```

It feels quite weird to use functions in the type parameters. Can this be efficiently compiled? Because the dimension is available at compiletime due to the type parameter but some functions are first called at runtime so this might cannot be optimized to the end. Is that correct?

Also, what to do if AT is not the first type parameter of SlidingWindowIterator?

---

<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 10, 2019, 7:18am UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/9 "2019-10-10T07:18:13Z")

</div>

> [@rapus95](#):
>
> It feels quite weird to use functions in the type parameters. Can this be efficiently compiled? Because the dimension is available at compiletime due to the type parameter but some functions are first called at runtime so this might cannot be optimized to the end. Is that correct?

No, it is not weird. The compiler should be able to optimize it out for concrete types.

> [@rapus95](#):
>
> Also, what to do if AT is not the first type parameter of SlidingWindowIterator?

Include other type parameters before it, rewrite your code that it is the first one, or define an accessor function (eg like [`ndims`](https://github.com/JuliaLang/julia/blob/09795cdd2e1d1af291d87122897a580c78352999/base/abstractarray.jl#L169)). See

[https://docs.julialang.org/en/v1/manual/methods/#Design-Patterns-with-Parametric-Methods-1](https://docs.julialang.org/en/v1/manual/methods/#Design-Patterns-with-Parametric-Methods-1)

---

<div class="post-metadata">

**Author:** ![rapus95](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rapus95/32/3773_2.png) [@rapus95](https://discourse.julialang.org/u/rapus95)\
**Post date:** [October 10, 2019, 1:38pm UTC](https://discourse.julialang.org/t/understanding-specialization-and-parametric-types/29680/10 "2019-10-10T13:38:02Z")

</div>

> [@Tamas\_Papp](#):
>
> [Methods · The Julia Language](https://docs.julialang.org/en/v1/manual/methods/#Design-Patterns-with-Parametric-Methods-1)

I didn’t know that page. Very much thanks for it!! I’ll link it at the first post for everyone else who might arrive here 🙂
