How to get default values of a functions kwargs

I came across the same need, and wrote a function for that.

From this stackoverflow similar question, it seems that code_lowered is the only function that holds the kwargs values, but in a confusing format if they are not “basic” types (Nothing or a custom type for example). Fortunately the values can be retrieved back!

"""
    get_kwargs(func_name::Function, args_types::Tuple)
Return a NamedTuple containing each supported kwarg and its default value for a given method.
# Arguments
- `func_name` is the name of the function
- `args_types` is a tuple of argument types for the desired method
"""
function get_kwargs(func_name::Function, args_types::Tuple)
    kwargs_names = Base.kwarg_decl(methods(func_name, args_types)[1])
    l = length(kwargs_names)
    if l==0
        # no kwargs
        return (;)
    else
        # lowered form of the method contains kwargs default values, but some are hidden
        code = code_lowered(func_name, args_types)[1].code
        str_code = ["$c" for c in code]
        # get index corresponding to the function
        index = findall(x -> occursin("$func_name", x), str_code)[1]
        # get lowered value of each kwarg
        values = code[index].args[2:2+l-1]
        # get back the original value according to the lowered value type
        kwargs_values = map(v -> 
            if v isa Core.SSAValue
                eval(code[v.id])
            elseif v isa GlobalRef
                eval(v)
            else 
                v
            end
            , values)
        # reconstruct kwargs
        NamedTuple(zip(kwargs_names, kwargs_values))
    end
end

Example function to test it:

struct MyType
    m::Int64
    t::String
end

myfunc(x::Float64; a=2, b=nothing, c="3", d=34.2, e=MyType(2,"two")) = println("test")

Retrieving kwargs:

get_kwargs(myfunc, (Float64,))

Result:

(a = 2, b = nothing, c = "3", d = 34.2, e = MyType(2, "two"))
6 Likes