# Parametric typing

**URL:** <https://discourse.julialang.org/t/parametric-typing/7298>\
**Category:** New to Julia\
**Tags:** parametric-types, functions\
**Created:** [November 25, 2017, 1:18am UTC](https://discourse.julialang.org/t/parametric-typing/7298 "2017-11-25T01:18:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jianghaizhu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jianghaizhu/32/1866_2.png) [@jianghaizhu](https://discourse.julialang.org/u/jianghaizhu)\
**Post date:** [November 25, 2017, 1:18am UTC](https://discourse.julialang.org/t/parametric-typing/7298/1 "2017-11-25T01:18:29Z")

</div>

I have a question about parametric typing in functions. Suppose I have 2 functions as follows.

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

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

```

They seem to behave the same to me. They both take `x` when `x` is a subtype of `Real` and produce the same result. What are the differences between them? In what circumstances should I use `<:`? Thanks!

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [November 25, 2017, 2:02am UTC](https://discourse.julialang.org/t/parametric-typing/7298/2 "2017-11-25T02:02:16Z")

</div>

This what I think about the subject:

I think that for functions with only one argument those two manners to define the type are equivalent, although the second one ( with `where {T<:Real}`), is more convenient when you have to use the type of the input in the body of the function. For example, the two functions produce the exact same machine code:

```julia
julia> function f(x::Real)
       y = zero(eltype(x))
       for i=1:div(x,2)
         y += i
       end
       end
f (generic function with 1 method)

julia> function g(x::T) where T<:Real
       y = zero(T)
       for i=1:div(x,2)
         y += i
       end
       end
g (generic function with 1 method)

julia> @code_native f(10)
	.section	__TEXT,__ text,regular,pure_instructions
Filename: REPL[1]
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 4
	popq	%rbp
	retq
	nopw	%cs:(%rax,%rax)

julia> @code_native g(10)
	.section	__TEXT,__ text,regular,pure_instructions
Filename: REPL[2]
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 4
	popq	%rbp
	retq
	nopw	%cs:(%rax,%rax)

julia> @code_native f(10.)
	.section	__TEXT,__ text,regular,pure_instructions
Filename: REPL[1]
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 3
	subq	$64, %rsp
	vmovsd	%xmm0, -8(%rbp)
	movabsq	$4665565568, %rax ## imm = 0x11616E180
	vmovsd	(%rax), %xmm1 ## xmm1 = mem[0],zero
	movabsq	$fmod, %rax
	callq	*%rax
	vmovsd	-8(%rbp), %xmm1 ## xmm1 = mem[0],zero
	vsubsd	%xmm0, %xmm1, %xmm0
	movabsq	$4665565576, %rax ## imm = 0x11616E188
	vmulsd	(%rax), %xmm0, %xmm0
	vroundsd	$4, %xmm0, %xmm0, %xmm2
	movabsq	$colon, %rax
	movabsq	$4665565584, %rcx ## imm = 0x11616E190
	vmovsd	(%rcx), %xmm0 ## xmm0 = mem[0],zero
	leaq	-56(%rbp), %rdi
	vmovapd	%xmm0, %xmm1
	callq	*%rax
	xorl	%eax, %eax
	movq	-24(%rbp), %rcx
	nopl	(%rax)
L112:
	addq	$1, %rax
	cmpq	%rax, %rcx
	jge	L112
Source line: 4
	addq	$64, %rsp
	popq	%rbp
	retq
	nop

julia> @code_native g(10.)
	.section	__TEXT,__ text,regular,pure_instructions
Filename: REPL[2]
	pushq	%rbp
	movq	%rsp, %rbp
Source line: 3
	subq	$64, %rsp
	vmovsd	%xmm0, -8(%rbp)
	movabsq	$4665570672, %rax ## imm = 0x11616F570
	vmovsd	(%rax), %xmm1 ## xmm1 = mem[0],zero
	movabsq	$fmod, %rax
	callq	*%rax
	vmovsd	-8(%rbp), %xmm1 ## xmm1 = mem[0],zero
	vsubsd	%xmm0, %xmm1, %xmm0
	movabsq	$4665570680, %rax ## imm = 0x11616F578
	vmulsd	(%rax), %xmm0, %xmm0
	vroundsd	$4, %xmm0, %xmm0, %xmm2
	movabsq	$colon, %rax
	movabsq	$4665570688, %rcx ## imm = 0x11616F580
	vmovsd	(%rcx), %xmm0 ## xmm0 = mem[0],zero
	leaq	-56(%rbp), %rdi
	vmovapd	%xmm0, %xmm1
	callq	*%rax
	xorl	%eax, %eax
	movq	-24(%rbp), %rcx
	nopl	(%rax)
L112:
	addq	$1, %rax
	cmpq	%rax, %rcx
	jge	L112
Source line: 4
	addq	$64, %rsp
	popq	%rbp
	retq
	nop

```

Now, when you have more than one input, there `where` syntax allows you to be more restrictive on the input of your function. For example:

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

julia> g(x::T,y::T) where {T<:Real} = x + y
g (generic function with 2 methods)

julia> f(1,1.)
2.0

julia> g(1,1.)
ERROR: MethodError: no method matching g(::Int64, ::Float64)
Closest candidates are:
  g(::T<:Real) where T<:Real at REPL[2]:2
  g(::T<:Real, ::T<:Real) where T<:Real at REPL[8]:1

julia> g(1,1)
2

julia> f(1,1)
2

```

With the `where` syntax you are able to enforce that both `x` and `y` must have the same concrete type.

---

<div class="post-metadata">

**Author:** ![jianghaizhu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jianghaizhu/32/1866_2.png) [@jianghaizhu](https://discourse.julialang.org/u/jianghaizhu)\
**Post date:** [November 25, 2017, 2:59am UTC](https://discourse.julialang.org/t/parametric-typing/7298/3 "2017-11-25T02:59:17Z")

</div>

Thanks for the example. Yes, when there are many arguments I often use the `T` method to enforce the same type. However, when there is only one argument, I am not sure they are the same. I found out that it doesn’t work on Arrays.

```julia
julia> f(x::Array{Real, 2}) = x .+ 1
f (generic function with 3 methods)

julia> g(x::Array{T, 2}) where {T<:Real} = x .+ 1
g (generic function with 3 methods)

julia> a = [1 2; 3 4]
2×2 Array{Int64,2}:
 1 2
 3 4

julia> f(a)
ERROR: MethodError: no method matching f(::Array{Int64,2})
Closest candidates are:
  f(::Array{Real,2}) at REPL[54]:1
  f(::Real) at REPL[41]:1

julia> g(a)
2×2 Array{Int64,2}:
 2 3
 4 5

```

---

<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:** [November 25, 2017, 3:15am UTC](https://discourse.julialang.org/t/parametric-typing/7298/4 "2017-11-25T03:15:09Z")

</div>

It doesn’t work because those are different types. An `Array{Real, 1}` is specifically an array for which each element can any subtype of Real. An `Array{Int, 1}` is not an `Array{Real, 1}`. But the syntax `Array{T, 1} where T <: Real` means an array where each element is of some specific type T which is a subtype of Real. That description matches lots of different arrays, including `Array{Int, 1}`, `Array{Float64, 1}`, etc.

---

<div class="post-metadata">

**Author:** ![jianghaizhu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jianghaizhu/32/1866_2.png) [@jianghaizhu](https://discourse.julialang.org/u/jianghaizhu)\
**Post date:** [November 25, 2017, 3:41am UTC](https://discourse.julialang.org/t/parametric-typing/7298/5 "2017-11-25T03:41:35Z")

</div>

You are absolutely right. Thanks for the clarification.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [November 25, 2017, 1:26pm UTC](https://discourse.julialang.org/t/parametric-typing/7298/6 "2017-11-25T13:26:27Z")

</div>

If you don’t need to use the element type inside the function, you can also do:

```julia
f(x::Array{<:Real, 2}) = x .+ 1
a = rand(0:9,2,2)
f(a)

```

---

<div class="post-metadata">

**Author:** ![jianghaizhu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jianghaizhu/32/1866_2.png) [@jianghaizhu](https://discourse.julialang.org/u/jianghaizhu)\
**Post date:** [November 25, 2017, 3:27pm UTC](https://discourse.julialang.org/t/parametric-typing/7298/7 "2017-11-25T15:27:38Z")

</div>

Yes, of course. I am mainly interested in my first example. In my second example, I was wrong. I simply forgot that `Array{Int, 2}` is not a subtype of `Array{Real, 2}` as was pointed out by @rdeits.
