julia реализует преобразование для структуры, содержащей NTuple - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь реализовать convert для структуры, содержащей NTuple:

import Base: convert

abstract type AbstractMyType{N, T} end

struct MyType1{N, T} <: AbstractMyType{N, T}
    data::NTuple{T, N}
end

struct MyType2{N, T} <: AbstractMyType{N, T}
    data::NTuple{T, N}
end

foo(::Type{MyType2}, x::AbstractMyType{N, T}) where {N, T} = x
convert(::Type{MyType2}, x::AbstractMyType{N, T}) where {N, T} = MyType2{T}(x.data)

println(foo(MyType2, MyType1((1,2,3))))         # MyType1{Int64,3}((1, 2, 3))
println(convert(MyType2, MyType1((1,2,3))))     # MethodError

Определенные функции foo и convert имеют одинаковую подпись. По какой-то причине функция foo нормально возвращается, а convert выдает MethodError. Почему Юля не может найти мой метод convert?

версия julia 1.4.1

Ответы [ 2 ]

1 голос
/ 30 мая 2020

Просто определите метод

convert(::Type{MyType2}, x::AbstractMyType{N, T}) where {N, T} = MyType2(x.data)

Тестирование:

julia> convert(MyType2, MyType1((1,2,3)))
MyType2{Int64,3}((1, 2, 3))
1 голос
/ 29 мая 2020

Julia is нахождение вашего метода преобразования:

julia> println(convert(MyType2, MyType1((1,2,3))))     # MethodError
ERROR: MethodError: no method matching MyType2{3,T} where T(::Tuple{Int64,Int64,Int64})
Stacktrace:
 [1] convert(::Type{MyType2}, ::MyType1{Int64,3}) at ./REPL[16]:1
 [2] top-level scope at REPL[18]:1

Эта трассировка стека говорит, что она находится внутри вашей convert функции (в моем случае я определил ее в первой строке 16-й подсказки REPL). Проблема в том, что он не может найти конструктор MyType2{T}(::Tuple).

Юлия автоматически создает для вас ряд конструкторов, если вы не используете внутренний конструктор; в этом случае вы можете вызвать MyType(()) или MyType{T, N}(()), но Джулия не знает, что делать, если передан только один параметр типа (по умолчанию):

julia> MyType2((1,2,3))
MyType2{Int64,3}((1, 2, 3))

julia> MyType2{Int, 3}((1,2,3))
MyType2{Int64,3}((1, 2, 3))

julia> MyType2{Int}((1,2,3))
ERROR: MethodError: no method matching MyType2{Int64,T} where T(::Tuple{Int64,Int64,Int64})
Stacktrace:
 [1] top-level scope at REPL[7]:1
 [2] eval(::Module, ::Any) at ./boot.jl:331
 [3] eval_user_input(::Any, ::REPL.REPLBackend) at /Users/mbauman/Julia/release-1.4/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:86
 [4] run_backend(::REPL.REPLBackend) at /Users/mbauman/.julia/packages/Revise/AMRie/src/Revise.jl:1023
 [5] top-level scope at none:0

Таким образом, исправление заключается в определите этот метод самостоятельно или измените тело вашего метода convert на явный вызов MyType{T,N}.

...