# Extract argument names

**URL:** https://discourse.julialang.org/t/extract-argument-names/862
**Category:** Internals & Design
**Tags:** question
**Created:** [December 11, 2016, 2:37pm UTC](https://discourse.julialang.org/t/extract-argument-names/862 "2016-12-11T14:37:36Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [December 11, 2016, 2:37pm UTC](https://discourse.julialang.org/t/extract-argument-names/862/1 "2016-12-11T14:37:36Z")

</div>

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:

1. care about positional argument names only, keywords are ignored
2. functions with one method: get argument names for that one
3. functions with more than one method: make the user pick with `which`
4. 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:

```julia
# 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:

1. is this roughly correct, or am I doing something stupid? please correct me.
2. 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

```julia
dostuff((x,y) -> x*y, collection) # with a closure

```

and

```julia
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.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 11, 2016, 5:56pm UTC](https://discourse.julialang.org/t/extract-argument-names/862/2 "2016-12-11T17:56:20Z")

</div>

> [@Tamas\_Papp](#):
>
> 1. should work for closures (they always have one method, right)?

No, you can add methods to an anonymous function using call overloading

```julia
f = (x) -> x^2
(T::typeof(f))(x,y) = x^2 + y^2

```

---

<div class="post-metadata">

### Author: ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)
#### Post date: [December 14, 2016, 5:48pm UTC](https://discourse.julialang.org/t/extract-argument-names/862/3 "2016-12-14T17:48:29Z")

</div>

That looks roughly right. The closest we have to a reference implementation is probably [julia/methodshow.jl at bfc72b6fe913236ccb2bdd1ef254bceccb0cc31a · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/blob/bfc72b6fe913236ccb2bdd1ef254bceccb0cc31a/base/methodshow.jl#L35) which handles printing methods.  
And as you noted, you generally need a concrete signature (e.g. the result of `which`) to have only a single answer. You shouldn’t dispatch on `::Function` since everything is callable, the functions you wrote will work on `Any` object type. However, if you don’t have a single `Method`, the most you can do is iterate over the `methods` list to aggregate the answer over all of the associated methods.
