2017-09-22 4 views
3

v06 2 ~ 3 개의 인수가 필요한 서명을 작성하고 싶습니다. 첫 번째 것은 정수 또는 정수의 벡터입니다. 두 번째 것은 Integer of Vector 또는 Integer of Matrix입니다. 세 번째는 Integer의 벡터이거나 지정되지 않은 벡터입니다. 나는 일치 할 수없는 것을 말해 오류가 발생이 foo(3, [0o7, 0o5]) 같은이를 호출 할 때 줄리아가 다중 발송에 실패했습니다

는 내가 처음이

function foo(
a::Union{Integer, Vector{Integer}}, 
b::Union{Vector{Integer}, Matrix{Integer}}, 
c::Union{Void, Vector{Integer}} = nothing) 

처럼 시도했다. 줄리아이 Array{UInt8} <: Array{Integer} == false 일치 할 수없는 이유

ERROR: LoadError: MethodError: no method matching foo(::Int64, ::Array{UInt8,1}) 
Closest candidates are: 
    foo(::Union{Array{Integer,1}, Integer}, !Matched::Union{Array{Integer,1}, Array{Integer,2}}) at ... 
    foo(::Union{Array{Integer,1}, Integer}, !Matched::Union{Array{Integer,1}, Array{Integer,2}}, !Matched::Union{Array{Integer,1}, Void}) at ... 

는 지금은 이해하지만 이것은 단지 줄리아의 스마트없는 것 같다.

은 그 때 나는 줄리아도 일치하지 않는 것을 말하지 않는 지금이

foo(a::Union{Z1, Vector{Z1}}, 
    b::Union{Vector{Z2}, Matrix{Z2}}, 
    c::Union{Void, Vector{Z3}} = nothing 
    ) where {Z1 <: Integer, Z2 <: Integer, Z3 <: Integer} 

을 시도!

ERROR: LoadError: MethodError: no method matching foo(::Int64, ::Array{UInt8,1}, ::Void) 
Closest candidates are: 
    foo(::Union{Array{Z1<:Integer,1}, Z1<:Integer}, ::Union{Array{Z2<:Integer,1}, Array{Z2<:Integer,2}}, ::Union{Array{Z3<:Integer,1}, Void}) where {Z1<:Integer, Z2<:Integer, Z3<:Integer} at ... 
    foo(::Union{Array{Z1<:Integer,1}, Z1<:Integer}, ::Union{Array{Z2<:Integer,1}, Array{Z2<:Integer,2}}) where {Z1<:Integer, Z2<:Integer} at ... 
+0

이와 같이 매우 복잡한 형식 시그니처가있는 경우, 특히 많은 유니온의 경우 여러 개별 메소드 정의로 분할해야한다는 신호 일 수 있습니다. 특히 foo (a, b, c)와 foo (a, b)를 선호하여 적어도 foo (a, b, c = nothing)를 피하기를 원할 것입니다. 또한 형식 사이에 연결이 있는지 여부를 고려하십시오. 예를 들어'b'가'Matrix' 인 경우에만'a'''Vector'입니까? – DNF

+0

@DNF 귀하의 우려를 이해합니다. 문제는 내가 그렇게하면 사용자가 유용한 쓸모없는 줄리아 오류 메시지를 쓰게된다는 것입니다. 예 : "어떤 방법도 b와 c의 행렬이 공존하지 않습니다." "이 행렬을 b로 지정하면이 차원을 가진 벡터로 c를 지정해야합니다"라는 식으로 표현합니다. 실제로이 서명은 모든 것을 점검하고 모든 것을 올바른 유형으로 캐스팅 한 후에 실제 메소드를 호출하는 헛소리 체크 서명입니다. – Nozdrum

+0

다중 발송이라는 아이디어에 반하는 명백한 입력 검사를 많이해야합니다. 평범한 줄리아 오류 메시지에 사람들이 노출되는 것을 피하기 위해 많은 고통을 느끼고 있습니다. 또한'c'가''Void'라고 말한 것에 놀랐습니다.''c ''를 전혀 제공하지 않으면! 제안 : 함수를 올바른 서명으로 별도의 메소드로 분할하십시오. 그런 다음'f (a, b, c) = ...'형식을 사용하지 않고 나머지를 포착하는 폴백 메서드 (또는 여러 개)를 만들고 입력 및 오류와 함께 잘못된 점을 찾아냅니다. – DNF

답변

6

예, Array{UInt8} <: Array{Integer} == false. 이것을 "파라 메트릭 불변성"이라고합니다. 다른 많은 질문이이 주제에 대해 논의했습니다.

당신이로 실행중인 다른 문제는, 그래도입니다 당신은 정적 함수 매개 변수를 사용할 때 - 즉, f(…) where T - 그것은 함수의 본문에 사용 가능한부터 T해야 일치 무엇인가. 이로 인해 Union에 문제가 발생합니다. 여기서 모든 옵션에서 T을 사용할 수 없습니다. 이 동작을 변경하여 T이 포함되지 않은 요소 인 Union과 일치하도록 허용하는 공개 문제가 있다고 생각합니다.이 요소에 액세스하려고 시도하면 정의되지 않은 변수로 바인딩됩니다.

지금 해결 방법은 이 함수의 정적 매개 변수가 아닌이 아닌 유형 vars를 사용하는 것입니다. 예 :

foo(a::Union{Integer, Vector{<:Integer}}, 
     b::Union{Vector{<:Integer}, Matrix{<:Integer}}, 
     c::Union{Void, Vector{<:Integer}} = nothing) = 1 
+0

IIRC, 예전에는 삼각형 디스패치가 지원되지 않았지만이 문제를 해결하기 위해 '유형 대체'를 정의해야합니다. 'typealias IntVector {T Integer} Vector {T}','foo (x :: Union {정수, IntVector}) = x'입니다. 더 이상 필요 없다는 것을 알았 기 때문에 다행입니다! – Gnimuc