# Finding the number of arguments of an anonymous function

**URL:** <https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394>\
**Category:** General Usage\
**Created:** [May 20, 2019, 9:35am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394 "2019-05-20T09:35:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 9:35am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/1 "2019-05-20T09:35:30Z")

</div>

I have an API wherein a kwarg is a function.

```julia
function apifunc(; f::Function = identity)
...
end

```

I would like to do something different depending on the number of arguments of `f`, so that `apifunc(f = x -> 2)` calls `_apifunc1(f)` but `apifunc(f = (x,y) -> 2)` calls `_apifunc2(f)`. Is there a way to achieve that, preferably in a non-dynamical way? In other words, is there any way to do introspection on the allowed signatures of a function’s methods?

---

<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:** [May 20, 2019, 9:40am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/2 "2019-05-20T09:40:34Z")

</div>

_Functions_ don’t have this information, their _methods_ do, eg

```julia
f() = 0
f(x) = 1
f(x, y) = 2

```

You would have to look up the method and from there it is possible to extract this information (using internals), but I would advise against it.

There is probably a cleaner and more idiomatic way to do what you want, but it is hard to say without more context.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [May 20, 2019, 10:14am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/3 "2019-05-20T10:14:27Z")

</div>

```julia
julia> f = x::Int -> 2;

julia> methods(f)
# 1 method for generic function "#13":
[1] (::getfield(Main, Symbol("##13#14")))(x::Int64) in Main at REPL[19]:1

julia> m = first(methods(f))
(::getfield(Main, Symbol("##13#14")))(x::Int64) in Main at REPL[19]:1

julia> m.nargs
2

julia> m.sig
Tuple{getfield(Main, Symbol("##13#14")),Int64}

```

etc.

I wouldn’t base an API on this though.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [May 20, 2019, 10:24am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/4 "2019-05-20T10:24:52Z")

</div>

To expand slightly on the previous answers: You might naively expect that the question is ill-defined for generic functions (that can have one method with one argument, and another method with two args, etc), but makes sense for anonymous functions.

This is not the case: Anonymous functions are just regular generic functions (with compiler-generated name instead of user-generated name) that can have many methods. You can add methods to an anonymous function by e.g.

```julia
julia> f_=x->x; (::typeof(f_))(x,y)=x+y; f_
#7 (generic function with 2 methods)

```

Even if there is only a single method, it still might be `VarArg`.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 10:58am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/5 "2019-05-20T10:58:44Z")

</div>

> I wouldn’t base an API on this though.

I assume this is because this is not guaranteed to remain like this, yes?

I feel a bit hampered when dealing with `Function` objects because there is little information that I can access about them. They seem a bit black-box to me, as compared to standard types. `methods` seems like the main point of access to these, but it’s not the first time I’ve read that we should not use this in our packages.

> There is probably a cleaner and more idiomatic way to do what you want, but it is hard to say without more context.

The context is this. I have a function `hamiltonian!(h; onsitefield = (o, i) -> o)` that takes a matrix `h` representing a Hamiltonian of a quantum system, and changes the diagonal element `h[i,i]` into `onsitefield(h[i, i], i)`. Now, I also want to allow the user to say `hamiltonian!(h; onsitefield = i -> some function of i)`, in which case `h[i,i]` should become `onsitefield(i)`. I don’t know how to do this, since in my code I have to hardcode either `onsitefield(h[i, i], i)` or `onsitefield(i)`. I would ideally like to use some form of dispatch to call one or the other, depending on the form of the `onsitefield` kwarg the user provides.

I come from Mathematica, where solving this is very easy. An anonymous function like `f = x -> cos(x)`, which in Mathematica is written as `f = Cos[#1]&`, can be called with any number of arguments, and the excess ones are just dropped, i.e. I can write `f[1,2,3,4,5]` and this returns `Cos[1]` without complaining. This would solve the above problem, but I don’t know how to replicate that in Julia.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 11:05am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/6 "2019-05-20T11:05:36Z")

</div>

(By the way, I’m aware that `f = (x, _...) -> cos(x)` replicates the Mathematica functionality, but that would force the user to never use the `onsitefield = i->...` form.)

---

<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:** [May 20, 2019, 11:08am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/7 "2019-05-20T11:08:09Z")

</div>

> [@pablosanjose](#):
>
> I don’t know how to do this, since in my code I have to hardcode either `onsitefield(h[i, i], i)` or `onsitefield(i)` . I would ideally like to use some form of dispatch to call one or the other, depending on the form of the `onsitefield` kwarg the user provides.

I am still not sure I understand the problem, but I guess the user could just pass a function that ignores the first argument if that is desired?

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 11:13am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/8 "2019-05-20T11:13:08Z")

</div>

Yes, that is always an option: just demand that `onsitefield` have always the general form `(o, i)-> ...`. I just hoped I could allow the user a simpler `i -> ...` syntax if her function does not depend on the existing onsite term `o`. If I do what you say, the user will just get a cryptic `MethodError` if she uses the simpler form.

(I do get the feeling that I’m probably trying to shoehorn a Mathematica way of thinking onto Julia…)

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 11:18am UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/9 "2019-05-20T11:18:21Z")

</div>

> julia\> m = first(methods(f))

Ah, I see that there might be another reason for the reluctance to use `methods`:

```julia
julia> @btime methods($f)
  1.923 μs (12 allocations: 720 bytes)

```

---

<div class="post-metadata">

**Author:** ![jbrea](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jbrea/32/3879_2.png) [@jbrea](https://discourse.julialang.org/u/jbrea)\
**Post date:** [May 20, 2019, 1:11pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/10 "2019-05-20T13:11:34Z")

</div>

I often use small structures when writing simulations where I want to try different behaviours of some sub-part. For example in a bigger simulation where I would use somewhere white noise or coloured noise, I would just define

```julia
struct WhiteNoise end
do_something_with(::WhiteNoise) = ...
struct ColouredNoise
    parameter::Float64
end
do_something_with(n::ColouredNoise) = ...

```

and write the rest of the simulation generic.

In your case you could wrap the functions into structures, e.g.

```julia
struct SingleArgumentFunction{F}
    f::F
end
struct TwoArgumentFunction{F}
    f::F
end

```

But there is certainly something more elegant along similar lines.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 1:14pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/11 "2019-05-20T13:14:56Z")

</div>

Thanks @jbrea, but forcing the user to wrap the function in a wrapper is equivalent to forcing the user to always use a `(o, i) -> ...` syntax. What I would want is precisely a way to apply the correct wrapper (single or two-argument) to a given anonymous function automatically, depending on the number of arguments taken by its methods. But I now think this is not the correct way to go about this. What I want might actually not be possible/advisable at this stage yet.

PS: perhaps with metaprogramming… Something like `@func i -> cos(i)` transforming into `(o,i) -> cos(i)`. That might be the better way.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [May 20, 2019, 1:20pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/12 "2019-05-20T13:20:52Z")

</div>

You could do this by looking through the method table and checking for one or two argument methods and call whichever one exists but of course you’d have to make a choice when both arities of method exist for the argument. You could also error if the function has more than a single method but that seems a bit restrictive.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 1:23pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/13 "2019-05-20T13:23:05Z")

</div>

Yeah, that was @kristoffer.carlsson’s suggestion. He advised against it, however (did not specify the reason). I would actually not mind that at all if `methods` weren’t so slow…

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [May 20, 2019, 1:25pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/14 "2019-05-20T13:25:39Z")

</div>

You can `try` to call with two arguments, and if it fails, call the 1 argument form. I would guess it may be faster than inspecting the method table.

(In the `REPL` module, you can find in many places a callback which should accept 3 arguments IIRC, and typically these are written as `(s, o...) -> ...`, there indeed doesn’t seem to exist a direct solution.)

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 1:27pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/15 "2019-05-20T13:27:04Z")

</div>

I’m afraid it is not

```julia
julia> t(f) = try; f(1); catch; f(1,2); end;
julia> h(x,y) = x+y;
julia> @btime t($h)
  25.134 μs (2 allocations: 48 bytes)
3

```

vs

```julia
julia> @btime first(methods($h)).nargs
  1.960 μs (12 allocations: 720 bytes)
3

```

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [May 20, 2019, 1:28pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/16 "2019-05-20T13:28:28Z")

</div>

Oh my, I did myself extremely basic benchmark and confused `μs` for `ns` 😊

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [May 20, 2019, 1:30pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/17 "2019-05-20T13:30:42Z")

</div>

This should be fast, but of course combines two evils:

```julia
Base.@pure function has_nargs(f, n)
    for m in methods(f)
        (m.nargs - 1) == n && return true
    end
    return false
end

function call(f)
    if has_nargs(f, 2)
        f(1, 2)
    else
        f(1)
    end
end

```

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 1:33pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/18 "2019-05-20T13:33:04Z")

</div>

HAHAHA!!! Nice! You used the Forbidden Word…

(I do not dare…)

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [May 20, 2019, 1:43pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/19 "2019-05-20T13:43:01Z")

</div>

@sdanisch, perhaps you could shine some light on the potential pitfalls of your approach? If I understand the implications well enough, I could be convinced to use this approach, but all the talk about missing backedges with `Base.@pure` and whatnot that apparently only Jameson understands scares me a little…

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [May 20, 2019, 2:30pm UTC](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394/20 "2019-05-20T14:30:01Z")

</div>

> [@pablosanjose](#):
>
> The context is this. I have a function `hamiltonian!(h; onsitefield = (o, i) -> o)` that takes a matrix `h` representing a Hamiltonian of a quantum system, and changes the diagonal element `h[i,i]` into `onsitefield(h[i, i], i)` . Now, I also want to allow the user to say `hamiltonian!(h; onsitefield = i -> some function of i)` , in which case `h[i,i]` should become `onsitefield(i)` . I don’t know how to do this, since in my code I have to hardcode either `onsitefield(h[i, i], i)` or `onsitefield(i)` . I would ideally like to use some form of dispatch to call one or the other, depending on the form of the `onsitefield` kwarg the user provides.

Why don’t you just document that the user should be giving a one argument function to the `kwarg` called `onsitefield`? If the function doesn’t have any single argument methods, you’ll get an error.

[Next page](https://discourse.julialang.org/t/finding-the-number-of-arguments-of-an-anonymous-function/24394.md?page=2)
