Keyword arguments of 32-bit type don't work

Why 32bit keyword argument functions give error (Int32 also) ?

julia> x = 2
2

julia> function sixty_four(x; y::Float64=0.5)
               x+y
       end
sixty_four (generic function with 1 method)

julia> function thirty_two(x; y::Float32=0.5)
               x+y
       end
thirty_two (generic function with 1 method)

julia> sixty_four(x)
2.5

julia> thirty_two(x)
ERROR: MethodError: no method matching var"#thirty_two#2"(::Float64, ::typeof(thirty_two), ::Int64)
The function `#thirty_two#2` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  var"#thirty_two#2"(::Float32, ::typeof(thirty_two), ::Any)
   @ Main REPL[3]:1

Stacktrace:
 [1] thirty_two(x::Int64)
   @ Main ./REPL[3]:1
 [2] top-level scope
   @ REPL[5]:1

0.5 is not a Float32. try 0.5f0

3 Likes

Ok, Thanks so i should first convert it to Float32.

julia> isa(0.5, Float32)
false

julia> isa(Float32(0.5), Float32)
true

This updated version thirty_two(x; y=Float32(0.5)) is also type stable. :smiley:

julia> x = 2
2

julia> function sixty_four(x; y::Float64=0.5)
               x+y
       end
sixty_four (generic function with 1 method)

julia> function thirty_two(x; y=Float32(0.5))
               x+y
       end
thirty_two (generic function with 1 method)

julia> sixty_four(x)
2.5

julia> thirty_two(x)
2.5f0

julia> @code_warntype thirty_two(x)
MethodInstance for thirty_two(::Int64)
  from thirty_two(x; y) @ Main REPL[9]:1
Arguments
  #self#::Core.Const(Main.thirty_two)
  x::Int64
Body::Float32
1 ─ %1 = Main.:(var"#thirty_two#52")::Core.Const(Main.var"#thirty_two#52")
│   %2 = Main.Float32::Core.Const(Float32)
│   %3 = (%2)(0.5)::Core.Const(0.5f0)
│   %4 = (%1)(%3, #self#, x)::Float32
└──      return %4

This also applies to positional arguments:

julia> f(x::Int32 = 1) = x
f (generic function with 2 methods)

julia> methods(f)
# 2 methods for generic function "f" from Main:
 [1] f(x::Int32)
     @ REPL[1]:1
 [2] f()
     @ REPL[1]:1

julia> @code_lowered f()
CodeInfo(
1 ─ %1 =   dynamic (#self#)(1)
└──      return %1
)

I.e. we here create two methods. The nullary version just calls f(1), which is undefined as there is no f(::Int64).

1 Like

This means that types are not checked during function definition. Types are inferred when the function is called or run on some value. :smiley:

What does dynamic refers to here ( i.e. type of variable %1 is not known or is dynamic)?

1 Like

You can do:

generic(x; y=0.5f0) = x+y

If you must restrict to floats:
generic(x; y::AbstractFloat=0.5f0) = x+y

or:

generic(x; y::Real=0.5f0) = x+y

These all take Float64 (and e.g. Float16, and Integers for the first), and if x is Float64 y the default arg gets converted to Float64.