I would like to process some functions according
to the number of their parameters and with regard
to the return value boolean.
function G(f::Function)
! hasparameters(f) && return 0
returnsboolean(f) && return 1
return 2
end
How can the query functions “hasparameters”
and “returnsboolean” be implemented?
Assume VERSION >= 0.6.
Edit: ChrisRackauckas’ solution seems to work for my purposes:
hasparameters(f) = 0 < maximum((length(m.sig.parameters) for m in methods(f))...)
returnsboolean(f) = first((methods(f)...)).specializations.func.rettype == Bool
function G(f::Function)
returnsboolean(f) && return 1 # query functions with parameters
hasparameters(f) && return 2 # functions with parameters
return 0 # functions with no parameters
end
Oh yes, if it’s defined as a normal function then it won’t have parameters. But callable types can. Not sure what else could be meant by this though. Number of arguments? That’s not well-defined either since you can have multiple methods, but this would work based on the maximum number:
function hasparameters(f)
numparam = maximum((length(m.sig.parameters) for m in methods(f))...)
numparam > 0
end
Return type can be dependent on the input type, so this is ill-defined the way you have it.
What I want to catch here are simple query functions like isprime, iseven, iszero etc. So I assume the return type is well defined as Bool. In any case am happy with a solution which works only in these cases (and possibly not in more general setups).
It’s deterministic so if it work in one run it should work in another run. If you want a function that returns true for the case you want it to or throw an error then sure it can be used like that. Otherwise it will not at all tell you what you want.
You should also describe the issue you want to solve more clearly. In julia there is not static return type, especially not for functions instead of methods so the classification you are talking about is not very well defined to begin with.
You should also describe the issue you want to solve more clearly.
That’s why I posted in the category “First Steps”. It may be a long time since you were a beginner, so I bring to your memory: not to be able to describe the problem clearly is an integral part of the difficulty with which a novice is struggling.
In julia there is not static return type, especially not for functions instead of methods so the classification you are talking about is not very well defined to begin with.
OK.
It’s deterministic so if it work in one run it should work in another run.
Also, if you don’t have a higher level description, you should at least give examples of the category of functions that you want to differentiate.
For example, your current version does this on 0.6.
julia> G(()->true)
ERROR: type Void has no field func
Stacktrace:
[1] G(::Function) at ./REPL[3]:2
julia> G(()->false)
ERROR: type Void has no field func
Stacktrace:
[1] G(::Function) at ./REPL[3]:2
julia> hasparameters(sin)
ERROR: type UnionAll has no field parameters
Stacktrace:
[1] append_any(::Base.Generator{Base.MethodList,##1#2}, ::Vararg{Base.Generator{Base.MethodList,##1#2},N} where N) at ./essentials.jl:160
[2] hasparameters(::Function) at ./REPL[1]:1
I’ll just add that there is no official way to do this, and calling methods will be extremely slow. This is basically a reflection-based approach, meaning you are digging in to system internals to find something out that’s not part of “normal” program flow.
I’ve applied the tricks of Chris now many times and it
has always worked. That it is ‘slow’ was never a problem.
Nevertheless, I do realize now that it is not quite the
Julian way to do things. So I’m still interested in
alternative implementations.
Basically I use them as a switch on the ‘type’ of function.
I give an example:
function g(A, f)
"fill the array A by using method f"
switch(f) :
if f returns a boolean do ...
if f returns an int do ...
etc...
end_switch
return A
end