julia - 基本结构的显示和播放错误
问题描述
我在定义复合类型时遇到了两个问题。
我正在关注 Julia v0.6 中手册的接口部分。我建立了一个简单的最小(非)工作示例:
mutable struct Group <: AbstractArray{Integer, 1}
x1::Int64
x2::Int64
end
Base.size(g::Group) = 2
Base.length(g::Group) = 2
Base.eltype(::Type{Group}) = Int64
Base.getindex(g::Group, i::Int64) = getindex([g.x1, g.x2], i)
Base.setindex!(g::Group, v, i::Int64) = Base.setindex!(g, v, i)
Base.IndexStyle(::Type{<:Group}) = IndexLinear()
Base.start(g::Group) = 1
Base.next(g::Group, s::Int) = g[s], s+1
Base.done(g::Group, s::Int) = (s > length(g))
Base.show(io::IO, g::Group) = print("\t", string(g.x1), "\n\t", string(g.x2))
很有希望:
julia> g = Group(1, 2);
julia> g.x1 = 42
42
julia> g.x1 = 99
99
julia> length(g)
2
julia> for i in h
@show i
end
i = 99
i = 2
但:
g = Group(1, 2)
这给出了错误(在 Juno 中):
Error displaying Group: MethodError: no method matching inds2string(::Base.OneTo{Int64})[0m
Closest candidates are:
inds2string([91m::Tuple{Vararg{AbstractUnitRange,N}} where N[39m) at show.jl:1568
_summary(::Group, ::Base.OneTo{Int64}) at show.jl:1573
#showarray#265(::Bool, ::Function, ::IOContext{Base.AbstractIOBuffer{Array{UInt8,1}}}, ::Group, ::Bool) at show.jl:1685
(::Atom.##17#18{Group})(::Base.AbstractIOBuffer{Array{UInt8,1}}) at display.jl:17
#sprint#230(::Void, ::Function, ::Int64, ::Function) at io.jl:66
Type at types.jl:39 [inlined]
Type at types.jl:40 [inlined]
render(::Juno.Editor, ::Group) at display.jl:19
render′(::Juno.Editor, ::Group) at errors.jl:105
(::Atom.##103#108{String})() at eval.jl:91
macro expansion at eval.jl:87 [inlined]
(::Atom.##100#105{Dict{String,Any}})() at task.jl:80
但:
help?> inds2string
search:
Couldn't find inds2string
Perhaps you meant randstring
No documentation found.
Binding inds2string does not exist.
第二个问题是因为我想使用广播:
julia> sin.(g)
然后我得到这个错误:
MethodError: Cannot `convert` an object of type Base.OneTo{Int64} to an
object of type CartesianRange
This may have arisen from a call to the constructor CartesianRange(...),
since type constructors fall back to convert methods.
CartesianRange(::Base.OneTo{Int64}) at sysimg.jl:77
broadcast_c at broadcast.jl:314 [inlined]
broadcast(::Function, ::Group) at broadcast.jl:455
include_string(::String, ::String) at loading.jl:522
include_string(::String, ::String, ::Int64) at eval.jl:30
include_string(::Module, ::String, ::String, ::Int64, ::Vararg{Int64,N}
where N) at eval.jl:34
(::Atom.##102#107{String,Int64,String})() at eval.jl:82
withpath(::Atom.##102#107{String,Int64,String}, ::Void) at utils.jl:30
withpath(::Function, ::String) at eval.jl:38
hideprompt(::Atom.##101#106{String,Int64,String}) at repl.jl:67
macro expansion at eval.jl:80 [inlined]
(::Atom.##100#105{Dict{String,Any}})() at task.jl:80
这不是很有帮助。我显然需要在Group
.
解决方案
问题是您的size
方法返回一个整数;size
应该返回一个具有每个维度长度的整数元组。在这种情况下,当我们定义一个向量时,它应该返回一个 1 元组,类似于:
Base.size(::Group) = (2, )
不幸的是,这导致下游的错误消息有些模糊。
其他一些可能有用的评论:
您的 getindex 有效,但分配了不必要的Vector
,也许像以下这样会更好:
function Base.getindex(g::Group, i::Int)
if i == 1
return g.x1
elseif i == 2
return g.x2
else
throw(BoundsError(g, i))
end
end
您对setindex!
调用本身的定义会导致StackOverflow
错误,也许像以下这样会更好:
function Base.setindex!(g::Group, v, i)
println("setindex!(:Group, v = $v, i = $i)")
if i == 1
g.x1 = v
elseif i == 2
g.x2 = v
else
throw(BoundsError(g, i))
end
end
推荐阅读
- r - 如何在这个 LOOP 中使用“DoParallel”,这需要我 12 小时以上才能运行
- qt - 在更改缩放之前无法获得 MapCircle 的宽度
- python - 使用会杀死内核的大型操作
- vb.net - 如何将输出发送到日志文件和富文本框
- php - 注销时未清除会话数据
- html - CSS脉动点,里面有文字
- ruby-on-rails - 未定义方法 `-' for nil:NilClass 用于现有字段的活动记录回调
- gatsby - Gatsby 构建错误“文档未定义”仅在 Netlify 上
- ios - iOS - Xcode 不作为 -> 动作按钮未“执行”定义的动作
- python - 如何在树视图中显示父目录?