Call macro in condition on run time

There are the codes:

struct A{T}
    n::T
end
(a::A{Int})(x::Vector) = begin
    res = similar
    for i = 1 : size(x, 1)
        res[i] = x[i]
    end
    res
end

(a::A{Float64})(x::Vector) = begin
    res = similar
    @threads for i = 1 : size(x, 1)
        res[i] = x[i]
    end
    res
end

When a.n isa Int, I need the loop block runs on main thread,and when a.n isa Float64, I need that runs on multi threads. But the two methods isa all same except only the @threads. Is there a way I can combine the two dispatched methods? Like:

(a::A{T})(x::Vector) where {T} = begin
    res = similar
    func(a) for i = 1 : size(x, 1)
        res[i] = x[i]
    end
    res
end
func(a::A{Int}) = @inbounds
func(a::A{Float64) = @threads

No. Macros are syntax transforms, they happen just after parsing and before the function itself exists. You can’t switch whether a macro is applied or not at runtime, they are always expanded.

If you want to switch between threaded and nonthreaded versions, you need either a runtime if to switch between different inlined versions or call different functions like in your first example.

1 Like

Or you use a generated function that splices in the threading macro if the argument is a Float64. This is almost kind of a “runtime macro” solution because the source code of the generated function is built using the type information received at runtime (but there will be no runtime overhead because compilation happens only once).

1 Like