Given a concrete type, one can define functor-like methods with:
struct Foo end
(f::Foo)(x) = 2x
and use the object as a function:
f = Foo()
f(1)
This doesn’t work with abstract types, however; even though they support abstract methods:
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.
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.
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.
I have encountered this before and also did not find a solution I am happy with. We basically work around this using something like
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
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