# Classification of functions

**URL:** https://discourse.julialang.org/t/classification-of-functions/4468
**Category:** New to Julia
**Tags:** question
**Created:** [June 26, 2017, 12:11pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468 "2017-06-26T12:11:42Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![leiteiro](https://avatars.discourse-cdn.com/v4/letter/l/b5e925/32.png) [@leiteiro](https://discourse.julialang.org/u/leiteiro)
#### Post date: [June 26, 2017, 12:11pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/1 "2017-06-26T12:11:42Z")

</div>

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

```

---

<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: [June 26, 2017, 1:33pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/2 "2017-06-26T13:33:12Z")

</div>

> [@leiteiro](#):
>
> hasparameters(f)

`length(typeof(f).parameters > 0)`

> [@leiteiro](#):
>
> returnsboolean(f)

Return type can be dependent on the input type, so this is ill-defined the way you have it.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 26, 2017, 1:59pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/3 "2017-06-26T13:59:20Z")

</div>

> [@ChrisRackauckas](#):
>
> length(typeof(f).parameters \> 0)

This will be `false` for all normal functions and is unlikely what he’s looking for (though I’m not sure what that is either…)

---

<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: [June 26, 2017, 2:15pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/4 "2017-06-26T14:15:20Z")

</div>

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:

```julia
function hasparameters(f)
  numparam = maximum((length(m.sig.parameters) for m in methods(f))...)
  numparam > 0
end

```

---

<div class="post-metadata">

### Author: ![leiteiro](https://avatars.discourse-cdn.com/v4/letter/l/b5e925/32.png) [@leiteiro](https://discourse.julialang.org/u/leiteiro)
#### Post date: [June 26, 2017, 2:26pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/5 "2017-06-26T14:26:11Z")

</div>

> function hasparameters(f)

Yes this seems to do what I want.

> 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).

---

<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: [June 26, 2017, 2:49pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/6 "2017-06-26T14:49:07Z")

</div>

```julia
returnsboolean(f) = first((methods(f)...)).specializations.func.rettype == Bool

```

That just uses the first method. Not sure how robust that is.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 26, 2017, 9:13pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/7 "2017-06-26T21:13:43Z")

</div>

This will not tell you what you want. It can only tell you if a method has been compiled that could return no wider than `Bool`.

---

<div class="post-metadata">

### Author: ![leiteiro](https://avatars.discourse-cdn.com/v4/letter/l/b5e925/32.png) [@leiteiro](https://discourse.julialang.org/u/leiteiro)
#### Post date: [June 27, 2017, 5:35am UTC](https://discourse.julialang.org/t/classification-of-functions/4468/8 "2017-06-27T05:35:09Z")

</div>

I think it depends. With ‘using Primes’ and ‘isprime’ I get indeed a “LoadError: type Void has no field func”. Is it this what you means?

However it will work if I define the query function more explicite as

```
  function Isprime(n)::Bool isprime(n) end

```

Or do you think even this could bring troubles?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 27, 2017, 6:35am UTC](https://discourse.julialang.org/t/classification-of-functions/4468/9 "2017-06-27T06:35:59Z")

</div>

Well, that one is basically returning random values so it is not guarantee to work in almost all cases…

---

<div class="post-metadata">

### Author: ![leiteiro](https://avatars.discourse-cdn.com/v4/letter/l/b5e925/32.png) [@leiteiro](https://discourse.julialang.org/u/leiteiro)
#### Post date: [June 27, 2017, 7:00am UTC](https://discourse.julialang.org/t/classification-of-functions/4468/10 "2017-06-27T07:00:27Z")

</div>

Then I do not understand you. In my small program it works so far in all cases.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 27, 2017, 10:06am UTC](https://discourse.julialang.org/t/classification-of-functions/4468/11 "2017-06-27T10:06:17Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![leiteiro](https://avatars.discourse-cdn.com/v4/letter/l/b5e925/32.png) [@leiteiro](https://discourse.julialang.org/u/leiteiro)
#### Post date: [June 27, 2017, 12:46pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/12 "2017-06-27T12:46:59Z")

</div>

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

Well, this is basically what I want. Thanks.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 27, 2017, 2:57pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/13 "2017-06-27T14:57:42Z")

</div>

> [@leiteiro](#):
>
> not to be able to describe the problem clearly is an integral part of the difficulty with which a novice is struggling.

What I mean is that you are likely trying to solve a problem in the wrong way so you should post what you actually want to do at a higher level.

> [@leiteiro](#):
>
> Well, this is basically what I want. Thanks.

I’m 100% sure it isn’t in this case. This is not better than a hard coded dict.

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 27, 2017, 3:12pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/14 "2017-06-27T15:12:37Z")

</div>

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
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

```

---

<div class="post-metadata">

### Author: ![jeff.bezanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff.bezanson/32/48_2.png) [@jeff.bezanson](https://discourse.julialang.org/u/jeff.bezanson)
#### Post date: [July 18, 2017, 3:14pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/15 "2017-07-18T15:14:37Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![leiteiro](https://avatars.discourse-cdn.com/v4/letter/l/b5e925/32.png) [@leiteiro](https://discourse.julialang.org/u/leiteiro)
#### Post date: [July 18, 2017, 4:38pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/16 "2017-07-18T16:38:43Z")

</div>

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

```

So what is the Julian way to achive this?

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [July 18, 2017, 4:57pm UTC](https://discourse.julialang.org/t/classification-of-functions/4468/17 "2017-07-18T16:57:16Z")

</div>

Pass in the type explicitly.
