首页 > 解决方案 > julia 为包含 NTuple 的结构实现转换

问题描述

我正在尝试实现一个convertfor 结构,其中包含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

定义的函数fooconvert具有相同的签名。由于某种原因,函数在throwsfoo时正常返回。为什么 Julia 找不到我的方法?convertMethodErrorconvert

朱莉娅版本 1.4.1

标签: methodstypesjulia

解决方案


Julia正在寻找您的转换方法:

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)构造函数。

当您不使用内部构造函数时,Julia 会自动为您创建多个构造函数;在这种情况下,您可以调用MyType(())or MyType{T, N}(()),但 Julia 不知道如何处理仅传递的一个类型参数(默认情况下):

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

因此,解决方法是自己定义该方法,或者将转换方法的主体更改为MyType{T,N}显式调用。


推荐阅读