I am trying to figure out the API for extracting argument names from (a method of a) function. What I want to achieve roughly looks like this:
- care about positional argument names only, keywords are ignored
- functions with one method: get argument names for that one
- functions with more than one method: make the user pick with
which
- should work for closures (they always have one method, right)?
I can live with the API for this being in flux, the library I am working on will test for my use cases so I can keep up with changes (I hope). But of course the more stable the better.
After reading the sources and looking at dump
s of various things, I came up with this:
# always try to find our way to this case
argument_names(li::LambdaInfo) = li.slotnames[2:end]
# method: unambiguous, use the lambda_template
argument_names(m::Method) = argument_names(m.lambda_template)
# this works for function names
function argument_names(f::Function)
m = methods(f)
length(m) == 1 || error("use `which` to pick from multiple methods")
argument_names(m[1])
end
# this works for closures
function argument_names{T <: Function}(l::T)
m = code_lowered(l)
length(m) == 1 || error("use `which` to pick from multiple methods")
argument_names(m[1])
end
# tests
foo(x::Int) = 2*x
argument_names(which(foo, (Int,))) # picking a method
argument_names(foo) # unambiguous
argument_names(x->2*x) # closures OK
argument_names((x;y=9) -> x*y) # keyword arguments OK
Questions:
- is this roughly correct, or am I doing something stupid? please correct me.
- is there an API already in place for what I am doing? maybe someone worked out a library for this?
Motivation (just in case you are curious): allow a user to apply a function f
do an associative collection Symbol => Vector
elementwise, picking the appropriate arguments from the collection. So
dostuff((x,y) -> x*y, collection) # with a closure
and
function thank_heavens_I_debugged_this(x,y)
x*y
end
dostuff(thank_heavens_I_debugged_this, collection)
should work. I am aware that various libraries use something like this, if you can point to a “canonical” implementation I could copy that would also help.