# Question on Idiomatic Julia, Traits, and Types

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.

``````
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

``````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.

``````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.

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`:

``````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:

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

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

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

``````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).

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

I think you want this:

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

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`.

1 Like

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

``````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
``````

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

``````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.