JuliaTokyo / julia-wakalang

Juliaのわからないことへの質問を雑にする場所
MIT License
25 stars 3 forks source link

Ambiguity warning #14

Closed oyamad closed 8 years ago

oyamad commented 8 years ago

Google で検索してもどうもヒットしないのでこちらで質問させていただきます.

function MyType(t::Tuple{}) を定義しろということだと思うのですが,中身は何を定義すればよいのでしょうか.

julia> type MyType
           N::Integer
           a::Real
       end

julia> function MyType{N}(t::NTuple{N,Int64})
           a = sum(t)
           return MyType(N, a)
       end
MyType

julia> function MyType{N}(t::NTuple{N,Float64})
           a = prod(t)
           return MyType(N, a)
       end
WARNING: New definition 
    call(Type{Main.MyType}, NTuple{#N<:Any, Float64}) at none:2
is ambiguous with: 
    call(Type{Main.MyType}, NTuple{#N<:Any, Int64}) at none:2.
To fix, define 
    call(Type{Main.MyType}, Tuple{})
before the new definition.
MyType

(実際はもう少し複雑なことをやっているのですが,簡単な例にしてみました.)

Method Ambiguities に説明があるようなケースなら理解できるのですが,上のような例では ambiguity がなさそうにも思えるのですが.

bicycle1885 commented 8 years ago

これは要素がない空のタプル型が唯一Tuple{}のみであるのに起因していると思います。 以下の例のように、2個目の型変数にIntが入ろうがFloat64が入ろうが同じ型(Tuple{})になります。

julia> NTuple{0,Int} === NTuple{0,Float64}
true

julia> NTuple{0,Int} === Tuple{}
true

julia> NTuple{0,Float64} === Tuple{}
true

ですので、N=0のときのどちらのメソッドを読んでよいか分からなくなるので、Tuple{}に対してメソッドを定義してあげれば、一番specificなTuple{}に対応するメソッドが呼ばれるようになり、曖昧性がなくなると思います。中身の定義は、空のタプルに対して呼ばれたときにどういう振る舞いを期待するかで決まると思います。

oyamad commented 8 years ago

ああなるほど,よくわかりました.ありがとうございました. (Tuple{}Tuple あるいは Tuple{Any} のことと勝手に誤解してました.)