How to check the possible parameters for a function in Julia

Sometimes I create functions that receive a function as parameter, but in Julia the type is Function without any information, so when the function pass as parameter is not right, the error message is not very informative:

By example:

julia> function fun_demo(f::Function)
       values = [1.0, 2.3, 3.4]
       return f.(values)
       end
each (generic function with 1 method)

julia> fun_demo(sin)
3-element Vector{Float64}:
  0.8414709848078965
  0.7457052121767203
 -0.2555411020268312

However, when the function is not right, the error is difficult to understand:

julia> fun_demo(lowercase)
ERROR: MethodError: no method matching lowercase(::Float64)
Closest candidates are:
  lowercase(::T) where T<:AbstractChar at ~/packages/julias/julia-1.7/share/julia/base/strings/unicode.jl:249
  lowercase(::AbstractString) at ~/packages/julias/julia-1.7/share/julia/base/strings/unicode.jl:540
Stacktrace:
     ...

That information is very confusing for the user that pass the function. I order to detect that, I have created a small function checkFunType:

function checkFunType(fun::Function,type::DataType)
    if (type <: Tuple)
        meths = methods(fun, type)
    else
        meths = methods(fun, Tuple{type})
    end
    return !isempty(meths)
end

So, we can do a more informative error message to user with:

function fun_demo(f::Function)
            @assert checkFunType(f, Float64) "Error: 'fun_demo' requires a function that receive a float and function '$(f)' does not do that"
           values = [1.0, 2.3, 3.4]
           return f.(values)
       end

In that case, the error is more useful:

ulia> fun_demo(lowercase)
ERROR: AssertionError: Error: 'fun_demo' requires a function that receive a float and function 'lowercase' does not do that
Stacktrace:
     ...

Of course, you can be more gentle that using @assert. The important think is that you can check the parameters that the function could receive, and act as you wish.

I have found it extremely useful when you are working with functions as parameters. I hope this could be useful for anyone.

PS It also work with generic types and with several parameters:

julia> checkFunType(sin, Int32)
true

julia> checkFunType(sin, String)
false

julia> checkFunType(sin, Real)
true

julia> checkFunType(+, Tuple{Int32, Int32})
true

julia> checkFunType(+, Tuple{Int32, String})
false
Avatar
Daniel Molina
Professor of Artificial Intelligence

My research interests include distributed robotics, mobile computing and programmable matter.

Related