Is the following function considered type-stable in Julia?

189 views Asked by At

I want to have a curried version of a function. So, I write the code as follows:

f(x::Int64, y::Int64) = x + y
f(x::Int64) = (y::Int64) -> f(x, y)

But I am not sure if Julia considers this an example of a type-unstable definition. On the face of it, one of the methods returns an anonymous function, while another returns an Int64. Yet, when the curried version is applied, the final result is also an Int64.

So, my questions are:

  1. Is this code type-stable?
  2. If not, is there a way to have a curried version of a function without writing type-unstable code?

Thanks in advance.

1

There are 1 answers

1
Shayan On BEST ANSWER

Yes, it is.
According to the official doc, you can investigate it by using the @code_warntype macro:

julia> @code_warntype f(1, 5)
MethodInstance for f(::Int64, ::Int64)
  from f(x::Int64, y::Int64) in Main at REPL[2]:1
Arguments
  #self#::Core.Const(f)
  x::Int64
  y::Int64
Body::Int64
1 ─ %1 = (x + y)::Int64
└──      return %1

The arguments of this function have the exact type Int64, and as we can see in the Body::Int64, the inferred return type function is Int64.

Furthermore, we have f(x) which is based on the type-stable function f(x, y):

julia> @code_warntype f(1)
MethodInstance for f(::Int64)
  from f(x::Int64) in Main at REPL[15]:1
Arguments
  #self#::Core.Const(f)
  x::Int64
Locals
  #3::var"#3#4"{Int64}
Body::var"#3#4"{Int64}
1 ─ %1 = Main.:(var"#3#4")::Core.Const(var"#3#4")
│   %2 = Core.typeof(x)::Core.Const(Int64)
│   %3 = Core.apply_type(%1, %2)::Core.Const(var"#3#4"{Int64})
│        (#3 = %new(%3, x))
└──      return #3

Here as well, there's not any unstable defined parameter type.
Look at the following as an example of an unstable-typed function:

julia> unstF(X) = x*5
unstF (generic function with 1 method)

julia> @code_warntype unstF(1)
MethodInstance for unstF(::Int64)
  from unstF(X) in Main at REPL[17]:1
Arguments
  #self#::Core.Const(unstF)
  X::Int64
Body::Any
1 ─ %1 = (Main.x * 5)::Any
└──      return %1

If you try this in the REPL, you'll see the Any appears with a red color. Since we have the Body::Any (Any with the red color), we can conclude that the returned object by this function is a non-concrete type object. Because the compiler doesn't know what is the x (Note that the input is X). So the result can be Anything! So this function is type-unstable for (here, for integer inputs. Note that you should investigate the type-stability of your function by your desired input(s). E.g., @code_warntype f(5) and @code_warntype f(5.) should be observed if I can pass it Float64 or Int64 either).