Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I generalize a custom type call function to an abstract type?

I have the following mock setup, with an abstract type, concrete types as subtypes, and a function f which takes two arguments, the first being a Letter.

abstract type Letter end

struct A <: Letter end
struct B <: Letter end

f(::A, x) = ('a', x)
f(::B, x) = ('b', x)

a = A()
b = B()

I would like to define a custom call function for Letter subtypes which simply calls f.

(t::A)(x) = f(t, x)
(t::B)(x) = f(t, x)

While this works, it seems quite redundant, especially considering that there could be many more subtypes of Letter. My attempts are as follows, but neither seem to work.

julia> (t::Letter)(x) = f(t, x)
ERROR: cannot add methods to an abstract type

julia> (t::T)(x) where T <: Letter = f(t, x)
ERROR: function type in method definition is not a type

How can I generalize a call function to match any (concrete) subtype of Letter?

like image 426
Harrison Grodin Avatar asked Nov 08 '22 20:11

Harrison Grodin


1 Answers

Building on Dan's answer, metaprogramming seems to be the way to go

for T in Symbol.(subtypes(Letter))
    @eval (t::$T)(x) = f(t, x)
end

generates functions per type.

Or:

for T in Symbol.(subtypes(Letter))
    c = Char(lowercase(first(String(T))))
    @eval f(::$T, x) = ($c, x)
    @eval (t::$T)(x) = f(t, x)
end

However, this use of structs/subtypes as enums is discouraged

like image 95
stillearningsomething Avatar answered Nov 15 '22 06:11

stillearningsomething