how to i get number of arguments of a function?

2,645 views
Skip to first unread message

Evan Pu

unread,
Oct 16, 2014, 11:55:01 AM10/16/14
to julia...@googlegroups.com
How do I get the number of arguments of a function?

for instance, f(x, y) = x + y

I want something like num_args(f), which will give me back 2. If the function has multiple methods then something more general would be nice, but so far I only care about functions with just a single method.

Is there something like this?
thanks alot!!

Tim Holy

unread,
Oct 16, 2014, 12:41:22 PM10/16/14
to julia...@googlegroups.com
You might want to look into the various introspection functions, like
`methods`, `code_lowered`, etc. Leah Hanson had a nice blog post:
http://blog.leahhanson.us/julia-introspects.html

For your specific problem, once you have a specific method, then `m.sig` returns
its signature, and you can just compute the length. A MethodTable (returned by
`methods(sum)`, for example) is iterable, so you can iterate over the table
until you find what you want.

Best,
--Tim

Evan Pu

unread,
Oct 16, 2014, 1:47:06 PM10/16/14
to julia...@googlegroups.com
thanks!!

Toivo Henningsson

unread,
Oct 16, 2014, 2:10:34 PM10/16/14
to julia...@googlegroups.com
Though you should probably look out for varargs methods too, the length of e.g. (Int...) is one, but a method with that signature can take any number of arguments.

Evan Pu

unread,
Oct 16, 2014, 2:12:20 PM10/16/14
to julia...@googlegroups.com
yeah, the function I'm intending to inspect will be defined by me and they shouldn't be varargs

ami...@gmail.com

unread,
Jan 21, 2016, 11:35:04 AM1/21/16
to julia-users
I'm using Julia v0.4.2 and I can't compute the length of what m.sig returns:

julia> function f(x)
       
end

julia
> for m in methods(f)
         println
(length(m.sig))
       
end
ERROR
: MethodError: `length` has no method matching length(::Type{Tuple{Int64,Int64}})

Since I'm trying to use the function length on a Type, and not on an instance of said Type. How can I do that?

Many thanks,

Yichao Yu

unread,
Jan 21, 2016, 12:09:27 PM1/21/16
to Julia Users
length(m.sig.parameters)

>
> Many thanks,

ami...@gmail.com

unread,
Jan 21, 2016, 12:47:38 PM1/21/16
to julia-users
Great, thanks a lot.
In fact, I also need to evaluate the number of arguments of an anonymous function:

julia> function factory(y)
         
return x -> x + y
       
end
factory
(generic function with 1 method)

julia
> type Foo
         f
::Function
       
end

julia
> foo = Foo(factory(2))
Foo((anonymous function))

julia
> methods(foo.f)
ERROR
: ArgumentError: argument is not a generic function
 
in methods at reflection.jl:180


Any way to do that..?

Jon Norberg

unread,
Jan 22, 2016, 4:49:31 AM1/22/16
to julia-users
Is it also possible to get a list of names of the variables used in a function? 

e.g.  for 

function f(x,y)
    k=0.1
    return x*y+k
end

I'd like to get a list ["k","x","y"]

My first thought was to make a method f() that returns this list, but if its possible to do this otherwise and more generally that would be very useful 

Mauro

unread,
Jan 22, 2016, 5:43:52 AM1/22/16
to julia...@googlegroups.com
> Is it also possible to get a list of names of the variables used in a
> function?
>
> e.g. for
>
> function f(x,y)
> k=0.1
> return x*y+k
> end
>
> I'd like to get a list ["k","x","y"]
>
> My first thought was to make a method f() that returns this list, but if
> its possible to do this otherwise and more generally that would be very
> useful

You'd have to inspect the AST. Looks like there is indeed a list in there:

julia> f(x,y) = (a=5;x+y+a)
f (generic function with 1 method)

julia> methods(f).defs.func.code
AST(:($(Expr(:lambda, Any[:x,:y], Any[Any[Any[:x,:Any,0],Any[:y,:Any,0],Any[:a,:Any,18]],Any[],0,Any[]], :(begin # none, line 1:
a = 5
return x + y + a
end)))))

You can get at it with:

julia> ast = Base.uncompressed_ast(methods(f).defs.func.code)
:($(Expr(:lambda, Any[:x,:y], Any[Any[Any[:x,:Any,0],Any[:y,:Any,0],Any[:a,:Any,18]],Any[],0,Any[]], :(begin # none, line 1:
a = 5
return x + y + a
end))))

julia> ast.args[2][1]
3-element Array{Any,1}:
Any[:x,:Any,0]
Any[:y,:Any,0]
Any[:a,:Any,18]

Jon Norberg

unread,
Jan 28, 2016, 2:40:35 AM1/28/16
to julia-users
Wow, thanks a lot, That one I would never had a chance to figure out.

Mauro

unread,
Jan 28, 2016, 8:03:52 AM1/28/16
to julia...@googlegroups.com
> Wow, thanks a lot, That one I would never had a chance to figure out.

It's easy enough, you could figure it out yourself too, knowing just a
few tricks. The essentials are here:
http://docs.julialang.org/en/release-0.4/devdocs/reflection/ plus the
tools: xdump, @less, @edit, @which.

In fact, I had to figure it out myself too, below is approximately what I
did. Note that this is due to the fact that most of Julia is written in
Julia, thus deep introspection is easy, unlike in many other high-level
languages.

NOTE: that these are internals, which can change anytime and will do so
without warning. In fact, the trick I showed you will most likely fail
on 0.5.

Julia REPL session:

julia> f(x,y) = (a=5;x+y+a)
f (generic function with 1 method)

julia> ms = methods(f)
# 1 method for generic function "f":
f(x, y) at none:1

julia> xdump(ms)
MethodTable
name: Symbol f
defs: Method
sig: Tuple{Any,Any}::DataType <: Any
va: Bool false
isstaged: Bool false
tvars: SimpleVector
length: Int64 0
func: (anonymous function)
invokes: Void nothing
next: Void nothing
cache: Void nothing
cache_arg1: Void nothing
cache_targ: Void nothing
max_args: Int64 2
kwsorter: #undef
module: Module Main


### Not sure why below xdump does not work, instead look at the fields directly:

julia> xdump(ms.defs.func)
ERROR: ArgumentError: invalid arguments to xdump
in xdump at show.jl:936

julia> fieldnames(ms.defs.func)
3-element Array{Symbol,1}:
:fptr
:env
:code

#### This is it. Except that it is not an Expr?!

julia> ms.defs.func.code
AST(:($(Expr(:lambda, Any[:x,:y], Any[Any[Any[:x,:Any,0],Any[:y,:Any,0],Any[:a,:Any,18]],Any[],0,Any[]], :(begin # none, line 1:
a = 5
return x + y + a
end)))))

julia> typeof(ms.defs.func.code)
LambdaStaticData

#### This is just gibberish:

julia> ms.defs.func.code.ast
102-element Array{UInt8,1}:
0x1d
0x08
0x03
0x23
...

### But it is displayed, thus look at how it is done. (if @edit
### doesn't work then use @less. Also @which is useful, which tells you
### where to look.)

julia> @edit show(ms.defs.func.code)

### Returns this wrapper: show(x) = show(STDOUT::IO, x)
### So check what gets called:

julia> @edit show(STDOUT, ms.defs.func.code)

### Ah, Base.uncompressed_ast transforms it into an Expr:

julia> Base.uncompressed_ast(ms.defs.func.code)
Reply all
Reply to author
Forward
0 new messages