我想定义一个函数f(x, t::Type)
,它根据isa(x, t)
执行不同的行为。我们想说如果是b1(x)
,我会打电话给b2(x)
,否则会function f(x, t::Type)
if isa(x, t)
b1(x)
else
b2(x)
end
end
。
我知道我可以在运行时进行动态检查,如下所示:
f{T}(x::T, t::Type{T}) = b1(x)
f(x, t::Type) = b2(x)
但是,有没有办法纯粹使用参数化方法调度?例如,如果我定义
f(1, Int)
对于f(1.0, Int)
和t
,会调用正确的行为。但我希望这也适用于f(1, Number)
的所有子类型:
b2
这实际上会调用 f
,因为f(x::Number, t::Type{Number}) = b1(x)
的第一个签名不匹配。有趣的是,f{T}(x::T, t::Type{T})
在这种情况下会匹配。
我错过了一些明显的东西吗?
这显然是一个错误,并在0.4中修复。
问题:
为什么f(1, Number)
与T
不匹配,即使Number
(f{T2, T1 <: T2}(x::T1, t::Type{T2})
)的类型替换匹配?< /秒>
使用t
或类似的东西不起作用,因为只有在关闭完整的静态参数列表后,所有静态参数才会出现在范围内。为什么呢?
使用动态方法是否有任何性能损失?
如何将方法定义为内部函数,所以我可以将function f(x, t::Type); g(x::t) = b1(x); g(x) = b2(x); g(x) end
绑定到局部变量,如下所示:
{{1}}
这有效,但性能成本是多少?
解决这个问题的惯用/首选方式是什么?
(我在0.3.2上试过这个。)
答案 0 :(得分:5)
回答你的问题:
isa(x, t)
并消除分支。但是,使用isa
可能还有一些不太可能的方法:
isa(x, t)
成为常量之前发生。 (这可能代价高昂;下面其他可能的去优化可能不是什么大问题。)isa
等相同的性能问题。isa
并不是一个糟糕的方法,前提是它不会导致类型推断问题。