# Functor abstract types

**URL:** https://discourse.julialang.org/t/functor-abstract-types/4887
**Category:** General Usage
**Tags:** question, type, functors
**Created:** [July 16, 2017, 8:46pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887 "2017-07-16T20:46:34Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)
#### Post date: [July 16, 2017, 8:46pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/1 "2017-07-16T20:46:34Z")

</div>

Given a concrete type, one can define functor-like methods with:

```julia
struct Foo end
(f::Foo)(x) = 2x

```

and use the object as a function:

```julia
f = Foo()
f(1)

```

This doesn’t work with abstract types, however; even though they support abstract methods:

```julia
abstract type A end
iscool(::A) = false # works just fine
(::A)(x) = 2x # fails, cannot add method to abstract type

```

Is there any way to define functor-like abstract types? I am just trying to avoid typing the same function for all subtypes of the abstract type manually.

---

<div class="post-metadata">

### Author: ![musm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/musm/32/3675_2.png) [@musm](https://discourse.julialang.org/u/musm)
#### Post date: [July 16, 2017, 8:49pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/2 "2017-07-16T20:49:03Z")

</div>

```julia
abstract type A end
struct Foo <: A end
struct Goo <: A end

iscool(::A) = false

f = Foo()
g = Goo()

julia> iscool(f)
false

julia> iscool(g)
false

(::Type{T})(x) where {T<:A} = 232

Foo(1) == 232
Goo(1) == 232

```

edit: I think I misunderstood the original question.

---

<div class="post-metadata">

### Author: ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)
#### Post date: [July 16, 2017, 8:55pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/3 "2017-07-16T20:55:08Z")

</div>

Thanks, doesn’t this syntax with `where` defines the function for all subtypes without the possibility of specialization? I forgot to say that I need to very rarely overwrite the definition for specific subtypes.

---

<div class="post-metadata">

### Author: ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)
#### Post date: [July 16, 2017, 9:14pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/4 "2017-07-16T21:14:08Z")

</div>

I have encountered this before and also did not find a solution I am happy with. We basically work around this using something like

```julia
for T in union(subtypes(DistanceLoss), subtypes(MarginLoss))
    @eval (loss::$T)(args...) = value(loss, args...)
end

```

but this has a serious drawback (among others) that it only works for subtypes defined before that loop is executed (which is why its the last block of code in the package)

As a side note, fallbacks do work for parametric types

```julia
julia> immutable Foo{N} end

julia> (::Foo)(x) = 2x

julia> Foo{2}()(3)
6

julia> Foo{3}()(3)
6

```

---

<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 16, 2017, 9:19pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/5 "2017-07-16T21:19:33Z")

</div>

> [@juliohm](#):
>
> Is there any way to define functor-like abstract types?

Currently no. [v0.5 "cannot add methods to an abstract type" when overriding call · Issue #14919 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/14919)

---

<div class="post-metadata">

### Author: ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)
#### Post date: [July 16, 2017, 9:31pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/6 "2017-07-16T21:31:00Z")

</div>

Thank you for sharing the issue @yuyichao, I will keep the code as is for now then.

---

<div class="post-metadata">

### Author: ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)
#### Post date: [July 16, 2017, 9:32pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/7 "2017-07-16T21:32:01Z")

</div>

Thanks @Evizero for the workaround, I will keep writing things manually, at least for now when it is still manageable.

---

<div class="post-metadata">

### Author: ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)
#### Post date: [November 6, 2017, 8:54am UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/8 "2017-11-06T08:54:09Z")

</div>

Wikipedia have an interesting article about “function object” (often called functor)

> **[Function object](https://en.wikipedia.org/wiki/Function_object)**
>
> In computer programming, a function object\[a\] is a construct allowing an object to be invoked or called as if it were an ordinary function, usually with the same syntax (a function parameter that can also be a function). Function objects are often called functors.
> A typical use of a function object is in writing callback functions. A callback in procedural languages, such as C, may be performed by using function pointers. However it can be difficult or awkward to pass a state into or out of the ...

Otherwise there is no example for Julia.

Maybe someone could provide an example there?

I also noticed that [https://github.com/lindahua/NumericFuns.jl](https://github.com/lindahua/NumericFuns.jl) provide functors… but it’s broken with Julia 0.6 see [https://github.com/lindahua/NumericFuns.jl/issues/9](https://github.com/lindahua/NumericFuns.jl/issues/9)  
Any news about it?

PS: Sorry, I should have post there [https://discourse.julialang.org/t/help-defining-functor-type/](https://discourse.julialang.org/t/help-defining-functor-type/)

---

<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: [November 6, 2017, 9:29am UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/9 "2017-11-06T09:29:58Z")

</div>

This is a classic example of a closure with state:

```julia
function make_counter()
    n = 0
    function()
        n += 1
    end
end

c = make_counter()

[c() for _ in 1:10] # will collect numbers from 1 to 10

```

But you can also get the same behaviour by using a mutable struct and making it callable:

```julia
mutable struct Counter
    n::Int
end

Counter() = Counter(0)

(c::Counter)() = c.n += 1

c = Counter()

[c() for _ in 1:10]

```

Arguably, the second one is easier to inspect, extend, and debug.

---

<div class="post-metadata">

### Author: ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)
#### Post date: [November 6, 2017, 8:12pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/10 "2017-11-06T20:12:53Z")

</div>

Thanks @Tamas_Papp I’ve just edit Wikipedia page “Function object” to add a Julia example with an accumulator implementation (both with mutable struct and with closure with state).  
This example is inspired from Python example

---

<div class="post-metadata">

### Author: ![ggggggggg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ggggggggg/32/265_2.png) [@ggggggggg](https://discourse.julialang.org/u/ggggggggg)
#### Post date: [November 6, 2017, 9:47pm UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/11 "2017-11-06T21:47:19Z")

</div>

Nice addition. “Such a accumulator” should be “Such an accumulator”

---

<div class="post-metadata">

### Author: ![scelles](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scelles/32/220408_2.png) [@scelles](https://discourse.julialang.org/u/scelles)
#### Post date: [November 7, 2017, 5:10am UTC](https://discourse.julialang.org/t/functor-abstract-types/4887/12 "2017-11-07T05:10:56Z")

</div>

Fixed. Thanks @ggggggggg for catching this
