# Parametric Types - am I using correctly

**URL:** <https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342>\
**Category:** General Usage\
**Tags:** question, parametric-types\
**Created:** [November 17, 2023, 12:14am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342 "2023-11-17T00:14:57Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)\
**Post date:** [November 17, 2023, 12:14am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342/1 "2023-11-17T00:14:57Z")

</div>

Wanted to check I’m using parametric types as intended.  
Two examples below comparing parametric types to using @match macro.  
I think parametric types are better but the macro does isolate the core logic nicely  
eg.  
:linear =\> a + x\*(b-a)  
:geo =\> a\*(b/a)^x

It would be nice to restrict the parameter values  
e.g. `struct interp_2{interp_type<:Interp_Type}`  
this would give an error in the below examples  
Is there a better method?  
Interested in any comments.

```julia
###### COMPARISON 1 #############
@enum Interp_Type linear geo

####### With Parametric Types ########3
struct interp_2{interp_type}
    a::Float64
    b::Float64
end

((;a,b)::interp_2{linear})(x) = a + x*(b-a)
((;a,b)::interp_2{ geo })(x) = a*(b/a)^x

interp_2{linear}(1,2)(.5) #1.5
interp_2{ geo }(1,2)(.5) #1.41421

########## With @match macro ##############
struct interp_2_2
    a::Float64
    b::Float64
    interp_type::Interp_Type
end

((;a,b,interp_type)::interp_2_2)(x) = @match Symbol(interp_type) begin
    :linear => a + x*(b-a) 
    :geo => a*(b/a)^x
end

interp_2_2(1,2,linear)(.5) #1.5
interp_2_2(1,2,geo )(.5) #1.41421

######## COMPARISON 2 #####################
@enum Day_Count ACT_365 ACT_360

###### with Parametric Type #############
struct coupon{day_count}
    days::Int64
end

Amount(c::coupon{ACT_365}) = c.days / 365
Amount(c::coupon{ACT_360}) = c.days / 360

Amount(coupon{ACT_360}(90)) #.25
Amount(coupon{ACT_365}(90)) #.2465

############# With @match macro ################
struct coupon_2
    day_count::Day_Count
    days::Int64
end

Amount(c::coupon_2) = @match Symbol(c.day_count) begin
    :ACT_360 => c.days / 360
    :ACT_365 => c.days / 365    
end

Amount(coupon_2(ACT_360,90)) #.25
Amount(coupon_2(ACT_365,90)) #.2465

```

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [November 17, 2023, 1:18am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342/2 "2023-11-17T01:18:25Z")

</div>

Just a minor note: Types are customarily typed in in “hammer” case. `Coupon2`, for instance, or `SpiffyTypeWithNoDiscerniblePurpose`. Makes it easier for readers of the code to make sense of it.

---

<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:** [November 17, 2023, 5:55am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342/3 "2023-11-17T05:55:09Z")

</div>

I don’t see anything wrong per se. You can also use a type parameter instead of a field in the `@match` version, they’re not mutually exclusive.

```julia
julia> @enum Interp_Type linear geo

julia> struct interp_2_3{interp_type}
           a::Float64
           b::Float64
       end

julia> using Match

julia> ((;a,b)::interp_2_3{T})(x) where T = @match Symbol(T) begin
           :linear => a + x*(b-a) 
           :geo => a*(b/a)^x
       end

julia> interp_2_3{linear}(1,2)(.5)
1.5

julia> interp_2_3{ geo }(1,2)(.5)
1.4142135623730951

```

The question is, do you need methods to be compiled separately for linear vs geo flags. If so, you can branch at compile-time, preferably via multimethods but may also occur when the compiler optimizes a method call, at the cost of compiling more code per flag. If not, store the flag in a field and use `@match` or an if-statement to branch at runtime.

---

<div class="post-metadata">

**Author:** ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)\
**Post date:** [November 18, 2023, 12:51am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342/4 "2023-11-18T00:51:18Z")

</div>

What are the pros and cons of branching at run time vs compile time?

---

<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:** [November 18, 2023, 1:58am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342/5 "2023-11-18T01:58:01Z")

</div>

Generally, the pros of compile-time branching is 1) don’t have to spend time branching at runtime, 2) restores type stability if the branches result in different types, 3) optimizations may go further if compiler can deduce only 1 branch runs. The con is having to compile a method more times, like for every concrete `interp_2_3{interp_type}`.

Whether a value should be a field or a type parameter depends on the situation. If a value takes arbitrarily many values, then it’s more worth to vary that per instance so you can compile a method once for all those values. If it only takes a few finite values and work separately (so you wouldn’t have an array mixing different `interp_type`s), it could be beneficial to make a type parameter you compile a few times for. Taking it to extremes, it seems obvious to make billions of `temperature::Float64` values vary per instance but ~5 `N::Int` values vary per `Array{T, N}` type.

---

<div class="post-metadata">

**Author:** ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)\
**Post date:** [November 24, 2023, 1:13am UTC](https://discourse.julialang.org/t/parametric-types-am-i-using-correctly/106342/6 "2023-11-24T01:13:32Z")

</div>

thanks for this 🙂
