# Question on Idiomatic Julia, Traits, and Types

**URL:** https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484
**Category:** General Usage
**Tags:** type, parametric-types, traits
**Created:** [January 25, 2023, 2:33am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484 "2023-01-25T02:33:42Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![TI36XPro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ti36xpro/32/33658_2.png) [@TI36XPro](https://discourse.julialang.org/u/TI36XPro)
#### Post date: [January 25, 2023, 2:33am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/1 "2023-01-25T02:33:42Z")

</div>

I’m trying to better learn and understand how to write idiomatic Julia. Please consider the following example. I have a some types defined as follows.

```julia

abstract type MyAbstractType end

Base.@kwdef struct MyStruct_1D <: MyAbstractType 
    # various fields that do not have a default value
    dim::Int = 1
end

Base.@kwdef struct MyStruct_2D <: MyAbstractType 
    # various fields that do not have a default value
    dim::Int = 2
end

```

These structs contain initial conditions, boundary conditions, physical parameters, and solutions on grids of either 1 or 2 dimensions, possibly 3 dimensions in the future. I want to define various methods that change behavior depending on the type. My naive approach then would be to do the following

```julia
function func1(s::MyStruct_1D)
# do 1D stuff
end

function func1(s::MyStruct_2D)
# do 2D stuff
end

```

Alternatively, I see traits talked about a lot. I don’t have much experience with them but I feel they are important and I should know how to implement them. I’m wondering if this is a good use case for them. I’m not certain it is, since the trait information is in the type name already (i.e., `_1D`). My naive first pass at implementing the above with traits would be to do something like this.

```julia
abstract type Dimension end
struct OneDimensional <: Dimension end
struct TwoDimensional <: Dimension end

Dimension(::Type{MyStruct_1D}) = OneDimensional()
Dimension(::Type{MyStruct_2D}) = TwoDimensional()

func1(s::T) where {T<:MyAbstractType} = func1(Dimension(T), s)

func1(::OneDimensional, s::T) where {T}
# do 1D stuff
end

func1(::TwoDimensional, s::T) where {T}
# do 2D stuff
end

```

I’m not sure which of the approaches is better. One last thing I thought about but I am not sure if its possible. Each struct has the `dim` field. Is it possible to somehow dispatch on that, using something like `Val()` to pass that information to the compiler?

I’d appreciate any thoughts on the above.

---

<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: [January 25, 2023, 2:44am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/2 "2023-01-25T02:44:30Z")

</div>

It’s not clear what the goal is here, perhaps you should give a more complete example, but one thing that I’m pretty sure of is that there’s no point to storing a field for dimension count inside a type that’s only ever intended to support 1D (or 2D, in the case of the other type). That’s redundant.

You could, for example, have a method `dimensions`:

```julia
dimensions(::Type{MyStruct_1D}) = 1
dimensions(::Type{MyStruct_2D}) = 2

```

That would make you `dim` field unnecessary.

Probably it would be even better if you could design a single type that would be parameterized by number of dimensions:

```julia
struct MyStruct_ND{dim} <: MyAbstractType ... end

```

---

<div class="post-metadata">

### Author: ![TI36XPro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ti36xpro/32/33658_2.png) [@TI36XPro](https://discourse.julialang.org/u/TI36XPro)
#### Post date: [January 25, 2023, 2:57am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/3 "2023-01-25T02:57:45Z")

</div>

Thanks for the response. The goal is stated below and I am just looking for advice on the best way to go about it.

> [@TI36XPro](#):
>
> I want to define various methods that change behavior depending on the type

I’m interested in your suggestion - but I’ve never implemented something like that before. I’d think something like

```julia
struct MyStruct_ND{dim} <: MyAbstractType
# various fields
end

```

I’d want to dispatch based on the type parameter, so maybe something like this? (though it does not work yet).

```julia
function func1(s::MyStruct_ND{dim}) where {dim} = 1
# Do 1-D stuff
end

```

---

<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: [January 25, 2023, 3:06am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/4 "2023-01-25T03:06:57Z")

</div>

> [@TI36XPro](#):
>
> `function func1(s::MyStruct_ND{dim}) where {dim} = 1`

I think you want this:

```julia
function func1(s::MyStruct_ND{1})
# Do 1-D stuff
end

```

---

<div class="post-metadata">

### Author: ![TI36XPro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ti36xpro/32/33658_2.png) [@TI36XPro](https://discourse.julialang.org/u/TI36XPro)
#### Post date: [January 25, 2023, 3:08am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/5 "2023-01-25T03:08:38Z")

</div>

Thank you! 🙂 I think this is the crux of what I was after. I knew there was a way to embed the dimensionality somehow into the type itself in a more elegant way then `_1D` or `_2D`.

---

<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: [January 25, 2023, 3:16am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/6 "2023-01-25T03:16:54Z")

</div>

The prototype for encoding dimensionality into the type is `AbstractArray{T,N}` and `Array{T,N}`:

```julia
julia> const NArray{N} = Array{T,N} where T
Array{T, N} where {N, T}

julia> NArray{1}
Vector (alias for Array{T, 1} where T)

julia> NArray{2}
Matrix (alias for Array{T, 2} where T)

julia> NArray{3}
Array{T, 3} where T

julia> NArray{4}
Array{T, 4} where T

```

---

<div class="post-metadata">

### Author: ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)
#### Post date: [January 25, 2023, 7:36am UTC](https://discourse.julialang.org/t/question-on-idiomatic-julia-traits-and-types/93484/7 "2023-01-25T07:36:39Z")

</div>

One advantage of the trait approach is that you can add your own dimension type to extend the method. For example

```julia
struct OneDFractal <: Dimension end
Dimension(::Type{MyStruct_Fractal}) = OneDFractal()
#dispatch
func1(::OneDFractal, s::T) where {T}
# do stuff
end

```

This is well explained in

Kwong, Tom. _Hands-on Design Patterns and Best Practices with Julia: Proven Solutions to Common Problems in Software Design for Julia 1.x_. Birmingham, UK: Packt Publishing, 2020.
