Override foo{x}

Is it possible to customize what happens when I do foo{x} for a particular type Foo or type X?

1 Like

Nope. You could write a macro though, e.g. @bar foo{x} can mean whatever you want it to mean.

Here’s what the syntax foo{x} lowers to:

julia> Meta.@lower foo{x}
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope'
1 ─ %1 = Core.apply_type(foo, x)
└──      return %1
))))

and looking at Core.apply_type,

julia> Core.apply_type
apply_type (built-in function)

we see that it is a built-in function and hence cannot have methods added to it

Expanding on this,

julia> e = :(foo{x})
:(foo{x})

julia> e.head
:curly

julia> e.args
2-element Vector{Any}:
 :foo
 :x

so

macro bar(e)
    v = e.args[1] # vector
    i = e.args[2] # index
    if e.head === :curly
        i = :(length(v) - $i + 1)
    end
    return esc(Expr(:ref, v, i))
end

gives you a (inefficient and difficult to understand) specialized syntax:

julia> foo = 1:10
1:10

julia> x = 2
2

julia> @bar foo[x] # get the second element
2

julia> @bar foo{x} # get the second to last element
9
1 Like
julia> struct Foo{T} x::T end

julia> Foo{Int}(x) = Foo{Float64}(Float64(x))

julia> Foo{Int}(3)
Foo{Float64}(3.0)