julia - 如何根据任何 splatted args 的类型进行调度?

标签 julia dispatch

考虑 Base 中的一个现有函数,它接受某种抽象类型的可变数量的参数 T 。我定义了一个子类型 S<:T并想编写一个方法,如果任何参数是我的子类型 S 则进行调度.

作为示例,请考虑函数 Base.cat ,与 TAbstractArrayS是一些MyCustomArray <: AbstractArray .

期望的行为:

julia> v = [1, 2, 3];

julia> cat(v, v, v, dims=2)
3×3 Array{Int64,2}:
 1  1  1
 2  2  2
 3  3  3

julia> w = MyCustomArray([1,2,3])

julia> cat(v, v, w, dims=2)
"do something fancy"

尝试:

function Base.cat(w::MyCustomArray, a::AbstractArray...; dims)
    pritnln("do something fancy")
end

但这仅在第一个参数为 MyCustomArray 时才有效。 .

实现这一目标的优雅方法是什么?

最佳答案

我想说,如果没有类型盗版,就不可能干净地做到这一点(但如果可能的话,我也想学习如何做)。

例如考虑 cat你问过的。它在 Base 中有一个非常通用的签名(实际上并不要求 A 是您所写的 AbstractArray):

julia> methods(cat)
# 1 method for generic function "cat":
[1] cat(A...; dims) in Base at abstractarray.jl:1654

你可以编写一个特定的方法:

Base.cat(A::AbstractArray...; dims) = ...

并检查 A 中是否有任何元素是你的特殊数组,但这将是类型盗版。

现在的问题是你甚至不能写 Union{S, T}S <: T以来它将被解析为 T .

这意味着您必须使用S明确地在签名中,但甚至:

f(::S, ::T) = ...
f(::T, ::S) = ...

有问题,编译器会要求您定义 f(::S, ::S)因为上述定义导致调度含糊不清。因此,即使您想将可变参数的数量限制为某个最大数量,您也必须为 A 的所有分区注释类型。分成子集以避免分派(dispatch)歧义(这可以使用宏实现,但所需方法的数量呈指数级增长)。

关于julia - 如何根据任何 splatted args 的类型进行调度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63285604/

相关文章:

julia - 自定义类型别名的 TypeError typeassert

python - 如何在 Julia 语言中使用 SVM?

python - win32com.client.Dispatch 有效但 win32com.client.gencache.EnsureDispatch 无效

ios - 无法在 Swift 中使用范围方法之外的变量(dataTaskWithRequest)

Julia:使用 splat 传递参数

julia - 预编译 StatsPlots.jl 失败

julia - Julia 有克罗内克三角洲吗?

bash:部分匹配到 case 的完整单词

c++ - 带有 std::variant 或 union 包装器的通用接口(interface)

action - NgRx 如何按顺序分派(dispatch) 2 个 Action