澄清 julia 中的函数签名和调度行为
Clarification on function signature and dispatching behaviour in julia
我在 Julia (1.2) REPL 中尝试了一些东西,但我一直在想一些我不了解调度的东西。
我第一次尝试了这个东西,它按我预期的方式工作:
f(a::T) where {T <: Int} = "Test"
自 Int <: Int == true
起调用 f(3) 有效
调用 f("Hello") 导致 "MethodError: no method matching" 错误,因为 String <: Int == false
然后,我尝试了这个方法,但我不明白为什么在某些情况下调用它会起作用:
f(a::T, b::U) where {T, U <: T} = "Another Test"
调用 f(3, 3) 有效(如我所料)
BUT f(3, "Hello") 也有效并且不会抛出 "MethodError: no method matching" ???
我认为(因为 T 变成了 Int 而 U 变成了 String)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}")
这里发生的事情是 T
可以是数据类型,而 U
可以是字符串的任何超类型。这样条件就满足了。 string 不是 int 的子类型让你感到困惑的事情是一个红色鲱鱼,因为没有具体类型是任何其他类型的子类型。
好的,多亏了laborg,我现在似乎明白发生了什么事了。如果我们采用这种方法:
f(a::T, b::U) where {T, U <: T} = "Another Test"
- 'T' 是 "UnionAll" 又名 "Iterated Union" 所有可能类型的 'a'。
'U' 是 "UnionAll" 又名 "Iterated Union" 'b' 的所有可能类型,它们是 'T'[=12 的子类型=]
我误解的事实是如果(示例)a::Int,那么 T 可以采用 typeof(a) 的父抽象类型。由于 Int <: Any,那么 T = Any 是调度的有效解决方案。
- U = Any 相同,因为 String <: Any。
所以我们现在有 U <: T 解析为 Any <: Any == true,然后调用该方法!
我希望我明白了:)
我在 Julia (1.2) REPL 中尝试了一些东西,但我一直在想一些我不了解调度的东西。
我第一次尝试了这个东西,它按我预期的方式工作:
f(a::T) where {T <: Int} = "Test"
自
Int <: Int == true
起调用 f(3) 有效
调用 f("Hello") 导致 "MethodError: no method matching" 错误,因为
String <: Int == false
然后,我尝试了这个方法,但我不明白为什么在某些情况下调用它会起作用:
f(a::T, b::U) where {T, U <: T} = "Another Test"
调用 f(3, 3) 有效(如我所料)
BUT f(3, "Hello") 也有效并且不会抛出 "MethodError: no method matching" ???
我认为(因为 T 变成了 Int 而 U 变成了 String)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}")
这里发生的事情是 T
可以是数据类型,而 U
可以是字符串的任何超类型。这样条件就满足了。 string 不是 int 的子类型让你感到困惑的事情是一个红色鲱鱼,因为没有具体类型是任何其他类型的子类型。
好的,多亏了laborg,我现在似乎明白发生了什么事了。如果我们采用这种方法:
f(a::T, b::U) where {T, U <: T} = "Another Test"
- 'T' 是 "UnionAll" 又名 "Iterated Union" 所有可能类型的 'a'。
'U' 是 "UnionAll" 又名 "Iterated Union" 'b' 的所有可能类型,它们是 'T'[=12 的子类型=]
我误解的事实是如果(示例)a::Int,那么 T 可以采用 typeof(a) 的父抽象类型。由于 Int <: Any,那么 T = Any 是调度的有效解决方案。
- U = Any 相同,因为 String <: Any。
所以我们现在有 U <: T 解析为 Any <: Any == true,然后调用该方法!
我希望我明白了:)