# Conversion and type stability

**URL:** https://discourse.julialang.org/t/conversion-and-type-stability/8692
**Category:** General Usage
**Tags:** type-stability, functions
**Created:** [January 30, 2018, 1:34pm UTC](https://discourse.julialang.org/t/conversion-and-type-stability/8692 "2018-01-30T13:34:45Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![Philippe\_Maincon](https://avatars.discourse-cdn.com/v4/letter/p/a4c791/32.png) [@Philippe\_Maincon](https://discourse.julialang.org/u/Philippe_Maincon)
#### Post date: [January 30, 2018, 1:34pm UTC](https://discourse.julialang.org/t/conversion-and-type-stability/8692/1 "2018-01-30T13:34:46Z")

</div>

I am writing a code in which the input file is a Julia script, and the user may provide some input in the form of functions (of one or several variables).

The code may use these functions by calling them with `Float64`, or with other datatypes. I have automatic differentiation in mind, but for this MWE, let us say it’s `Int64` vs. `Float64`.

Now, most input functions would use all their inputs  
`f = (x,y) -> x^2+y`  
but the user may say “Oh the input parameters do not really matter”  
`g = (x,y) -> 1`

This causes me two types of problems

**a)** If I call an input function with two `Float64`, two `Int64`, or with an `Int64` and a `Float64`. I need to rely on the output being `promote_type(typeof(x),typeof(y))`, that is, `Float64`.

Without countermeasures, calling `g` would wreak havoc in my dispatching logic further down the line. That issue, I can solve:

```julia
promote_eltype(v...) = promote_type(eltype.(v)...)
convert_eltype(a,v...) = convert(promote_eltype(a,v...),a)
typestable(f,x...) = convert_eltype(f(x...),x...)::promote_eltype(x)
F(x...) = typestable(g,x...)
G(x...) = typestable(f,x...)

```

So if I use `F` and `G` in place of `f` and `g`, my software does the computations I want.

**b)** _But_ it does it slowly. Behold:

```julia
> @code_warntype typestable(f,3,2.)

Variables:
  #self#::#typestable
  f::##49#50
  x::Tuple{Int64,Float64}

Body:
  begin 
      SSAValue(0) = (Core.getfield)(x::Tuple{Int64,Float64}, 1)::Int64
      return (Base.add_float)((Base.sitofp)(Float64, (Base.mul_int)(SSAValue(0), SSAValue(0))::Int64)::Float64, (Core.getfield)(x::Tuple{Int64,Float64}, 2)::Float64)::Float64
  end::Float64

> @code_warntype F(3,2.)

Variables:
  #self#::#F
  x::Tuple{Int64,Float64}

Body:
  begin 
      SSAValue(1) = Main.g
      SSAValue(3) = (Core.getfield)(x::Tuple{Int64,Float64}, 1)::Int64
      SSAValue(4) = (Core.getfield)(x::Tuple{Int64,Float64}, 2)::Float64
      $(Expr(:inbounds, false))
      # meta: location untitled-33e486cf08c224e1e95c30ab1d254fb4 typestable 8
      SSAValue(2) = (SSAValue(1))(SSAValue(3), SSAValue(4))::ANY
      # meta: pop location
      $(Expr(:inbounds, :pop))
      return (Core.typeassert)((Main.convert_eltype)(SSAValue(2), SSAValue(3), SSAValue(4))::ANY, $(QuoteNode(Real)))::REAL
  end::REAL

```

So while calling “typestable” gives me, well, typestable code, any attempt at a syntactic sugar wrap makes me lose type stability.

I can live without the syntactic sugar, but if the implication is that typestability is not “exported by a function” then I am in CPU-trouble, and worse, I do not understand the logic of it all.

What is going on here, why are F and G not typestable, when they return a value that is stamped for type?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [January 30, 2018, 1:40pm UTC](https://discourse.julialang.org/t/conversion-and-type-stability/8692/2 "2018-01-30T13:40:02Z")

</div>

global nonconst variables are bad, mkay.

```julia
const f = (x,y) -> x^2+y
const g = (x,y) -> 1

```

```julia
julia> @code_warntype F(3,2.)
Variables:
  #self# <optimized out>
  x <optimized out>

Body:
  begin
      return (Base.sitofp)(Float64, $(QuoteNode(1)))::Float64
  end::Float64

```

You could also just define non anonymous functions like:

```julia
f(x,y) = x^2 + y

```

Note that your `F` calls `g` and `G` calls `g`, probably just a typo.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon](https://avatars.discourse-cdn.com/v4/letter/p/a4c791/32.png) [@Philippe\_Maincon](https://discourse.julialang.org/u/Philippe_Maincon)
#### Post date: [January 30, 2018, 1:49pm UTC](https://discourse.julialang.org/t/conversion-and-type-stability/8692/3 "2018-01-30T13:49:00Z")

</div>

Thanks, as usual, great help from you.

F = …g… not a problem in the MWE, but would look bad in the software!!!😀

I am trying the get the logic: if f is a non-const closure, I can define F, and _then_ redefine f, and that keeps the compiler very cautious. If f is a const closure, I’d have to recompile to redefine it.

But if f is a function-not-closure f(x,y) = x^2+y then I can still redefine it. And this affects the behaviour of F, _but_ F is typestable. Hmm… why?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [January 30, 2018, 1:56pm UTC](https://discourse.julialang.org/t/conversion-and-type-stability/8692/4 "2018-01-30T13:56:32Z")

</div>

`f` is not a closure here, it is just a non const binding to the anonymous function `(x,y) -> x^2 + y`. And since you are accessing `f` from `F` you are using a non const global binding.

> [@Philippe\_Maincon](#):
>
> But if f is a function-not-closure f(x,y) = x^2+y then I can still redefine it. And this affects the behaviour of F, but F is typestable. Hmm… why?

Because Julia has special functionality for dealing with the case of redefining functions. If you redefine the function `f`, what the compiler (basically) will do is to recompile everything that depends on the result of `f`. And since everything is recompiled with the new `f` in mind, then it is type stable again.

---

<div class="post-metadata">

### Author: ![Philippe\_Maincon](https://avatars.discourse-cdn.com/v4/letter/p/a4c791/32.png) [@Philippe\_Maincon](https://discourse.julialang.org/u/Philippe_Maincon)
#### Post date: [January 30, 2018, 2:04pm UTC](https://discourse.julialang.org/t/conversion-and-type-stability/8692/5 "2018-01-30T14:04:02Z")

</div>

Non-const binding, vs. redefining-is-recompiling a function. Got it! Thanks a million!

This const business got me trice. Once with non-const global variables, then non-const type aliases, and now, non-const binding to an anonymous function! When will I learn…
