# Elaboration on Parametric Methods

**URL:** https://discourse.julialang.org/t/elaboration-on-parametric-methods/61531
**Category:** General Usage
**Created:** [May 20, 2021, 6:04pm UTC](https://discourse.julialang.org/t/elaboration-on-parametric-methods/61531 "2021-05-20T18:04:24Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![anon60034542](https://avatars.discourse-cdn.com/v4/letter/a/90ced4/32.png) [@anon60034542](https://discourse.julialang.org/u/anon60034542)
#### Post date: [May 20, 2021, 6:04pm UTC](https://discourse.julialang.org/t/elaboration-on-parametric-methods/61531/1 "2021-05-20T18:04:24Z")

</div>

I don’t fully grasp when you would use parametric types or abstract types in methods.

Before posting my question, I did attempt to [read](https://softwareengineering.stackexchange.com/a/308064) and try and answer the question for myself.

Consider the following code:

```julia
abstract type Character end
abstract type Alien <: Character end

struct Gray <: Alien
    name::String
    age::Int32
    favourite_food::String
end

struct BlueAlien <: Alien
    name::String
    favourite_song::String
end

struct Human <: Character
    name::String
end 

```

Consider the following function that uses the `where` keyword:

```julia
function share_food(character_that_has_food::A,
                    character_that_receives_food::A,
                    food::String) where {A <: Character}
     
     println("Working with $(typeof(character_that_has_food)) and 
             $(typeof(character_that_receives_food))")

     println("Sharing a $(food) with my friend 
             $(character_that_receives_food.name)")
end

mort = Gray("Mort",1000,"Fries")
zorotl = BlueAlien("Zorotl","Blue - Eiffel 65")
share_food(mort,zorotl,"Cheese Burger and Apple Pie")

```

I don’t see any distinction between the above function and this function:

```julia
function share_food(character_that_has_food::Character,
                    character_that_receives_food::Character,
                    food::String)

    println("Working with $(typeof(character_that_has_food)) and   
            $(typeof(character_that_receives_food)).")

    println("Sharing a $(food) with my friend 
             $(character_that_receives_food.name).")
end

```

Both do the same thing but in a different ways. The first `share_food()` example uses `A` as the variable, and I can use that variable just like any other variable.

1. What situation would you use that variable containing the type? The only situation that I can think of is when you want to do something with a type, but don’t care about the type.

For example, create a collection of aliens `generate_alien_vector(aliens_from_db::A) where A <: Alien`. Now I don’t care what alien I pass in to generate the vector.

The problem is, with just abstract types I can do the same thing, because Julia knows the specific type it’s given. For example, calling the above `share_food()` function without the `where`:

```julia
Working with Gray and BlueAlien.
Sharing a Cheese Burger and Apple Pie with my friend Zorotl.

```

I can even capture the result of `typeof()` and use it to create a collection.

The example shown in the above link uses generics to allow any type of `IBusinessObject` but still be able to retrieve the concrete type to call the properties specifc to that type.

1. Can you carry out a task with parametric functions that you can’t with functions that accept only abstract types?

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [May 20, 2021, 6:11pm UTC](https://discourse.julialang.org/t/elaboration-on-parametric-methods/61531/2 "2021-05-20T18:11:20Z")

</div>

They are not exactly the same thing:

```julia
julia> f(x::Real,y::Real) = x + y
f (generic function with 1 method)

julia> f(1,1.0)
2.0

julia> g(x::T,y::T) where T<:Real = x + y
g (generic function with 1 method)

julia> g(1,1.0)
ERROR: MethodError: no method matching g(::Int64, ::Float64)
Closest candidates are:
  g(::T, ::T) where T<:Real at REPL[3]:1
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1

```

the parametric form only works if both input types are the same.

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [May 20, 2021, 6:13pm UTC](https://discourse.julialang.org/t/elaboration-on-parametric-methods/61531/3 "2021-05-20T18:13:25Z")

</div>

Edit: @lmiq beat me to it by one minute 😉

The distinction is that the first method requires that the two characters have the _same_ type (and that that must be some subtype of `Character`. Here’s a simpler example:

```julia
julia> function f(x::T, y::T) where {T <: Integer}
         x + y
       end
f (generic function with 1 method)

julia> f(Int32(1), Int64(1))
ERROR: MethodError: no method matching f(::Int32, ::Int64)
Closest candidates are:
  f(::T, ::T) where T<:Integer at REPL[6]:1
Stacktrace:
 [1] top-level scope
   @ REPL[8]:1

julia> function g(x::Integer, y::Integer)
         x + y
       end
g (generic function with 1 method)

julia> g(Int32(1), Int64(1))
2

```

A further difference is that having an explicit type parameter lets you express more complicated relationships, such as:

```julia
julia> function h(x::T, y::Matrix{T}) where {T}
         x * y
       end
h (generic function with 1 method)

julia> h(2.0, ones(Float64, 2, 2))
2×2 Matrix{Float64}:
 2.0 2.0
 2.0 2.0

```

here `h` is a function that will take any `x` and a `y` whose scalar type is the same as the type of `x`, whatever that type may be. That’s not a relationship you can express via dispatch without type variables.
