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.
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).