澄清 julia 中的函数签名和调度行为

Sno*_*wop 8 typing dispatch julia

我在 Julia (1.2) REPL 中尝试了一些东西,但我一直在想一些我不了解调度的东西。


我首先尝试了这件事,它按我预期的方式工作:

f(a::T) where {T <: Int} = "Test"

  • 调用 f(3) 有效 Int <: Int == true

  • 调用 f("Hello") 会导致“MethodError: no method matching”错误,因为 String <: Int == false


然后,我尝试了这个方法,我不明白为什么在某些情况下调用它有效:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • 调用 f(3, 3) 有效(如我所料)

  • 但是 f(3, "Hello") 也可以工作并且不会抛出“MethodError: no method matching”???

我认为(因为 T 变成了一个 Int 而 U 变成了一个字符串)String <: Int == false???


我想我在这里遗漏了一些非常简单的东西,但我找不到它......所以这是我的问题,为什么 f(3, "Hello") 正在工作???


此外,我尝试了这段代码(我尝试重新创建第二个方法签名),但正如我所料,它正确地失败了:

Test = Tuple{T, U} where {T, U <: T}

Test{Int, String} (这与我预期的“TypeError: in Type, in U, expected U<:Int64, got Type{String}”一样失败)

Sno*_*wop 3

好吧,多亏了Laborg,我现在似乎明白发生了什么事。如果我们采用这种方法:

f(a::T, b::U) where {T, U <: T} = "Another Test"

  • 'T' 是所有可能类型 'a' 的“UnionAll”,又名“迭代并集”。
  • 'U' 是 'b' 的所有可能类型('T' 的子类型)的“UnionAll”,又名“迭代并集”

  • 我的误解是,如果(例如)a::Int,那么 T 可以采用 typeof(a) 的父抽象类型。由于 Int <: Any,因此 T = Any 是调度的有效解决方案。

  • 对于 U = Any 也是如此,因为 String <: Any。

所以我们现在有 U <: T 解析为 Any <: Any == true,并且该方法被调用!

我希望我能得到它:)