英文:
Method error in Julia when using Parameters.jl
问题
我想定义如下变量,但当我添加这一行time::Vector{Float32}=[a:step:b]
时不起作用
使用 Parameters
@with_kw mutable struct variables
InetrpolationDegree::Int = 1
a::Float32 = 0.0
b::Float32 = 15.0
N::Int = 100
step::Float32 = (b-a)/N
time::Vector{Float32}=[a:step:b]
end
t = variables(N=100).time;
Δt = variables(N=100).step;
s = variables(N=100).InetrpolationDegree
我收到了以下错误消息
MethodError: 无法将类型为 StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64} 的对象转换为类型 Float32
英文:
I want to define variables as below, but does not when I add the line time::Vector{Float32}=[a:step:b]
using Parameters
@with_kw mutable struct variables
InetrpolationDegree::Int = 1
a::Float32 =0.0
b::Float32 =15.0
N::Int = 100
step::Float32 = (b-a)/N
time::Vector{Float32}=[a:step:b]
end
t=variables(N=100).time;
Δt=variables(N=100).step;
s=variables(N=100).InetrpolationDegree
I got this this error
> MethodError: Cannot convert
an object of type StepRangeLen{Float64,
> Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64} to
> an object of type Float32
答案1
得分: 0
你应该知道,通过 a:step:b
构建的对象是 AbstractRange
抽象类型的子类型。因此,将它包装在方括号 [a:step:b]
内不会创建一个 Vector{Float32}
类型的对象!因此,你应该在大括号内声明正确的类型。由于返回的对象是一个 Vector
,其中元素是一个 <:AbstractRange
对象(读作:AbstractRange 的子类型),我们可以这样说:
time::Vector{<:AbstractRange}=[a:step:b]
@with_kw mutable struct variables
InetrpolationDegree::Int = 1
a::Float32 = 0.0
b::Float32 = 15.0
N::Int = 100
step::Float32 = (b-a)/N
time::Vector{<:AbstractRange} = [a:step:b]
end;
t = variables(N=100).time;
Δt = variables(N=100).step;
s = variables(N=100).InetrpolationDegree # 返回 1
附加说明
请记住,你还可以使用 Base.@kwdef
而不是 @with_kw
。
英文:
You should be aware that the constructed object through a:step:b
is subtype of the AbstractRange
AbstractType. So wrapping it within brackets [a:step:b]
won't make an object of type Vector{Float32}
! Thus, you should declare the correct type within braces. Since the returned object is a Vector
, which in the element is an object <:AbstractRange
(read it: subtype of AbstractRange), we can say:
time::Vector{<:AbstractRange}=[a:step:b]
@with_kw mutable struct variables
InetrpolationDegree::Int = 1
a::Float32 =0.0
b::Float32 =15.0
N::Int = 100
step::Float32 = (b-a)/N
time::Vector{<:AbstractRange}=[a:step:b]
end;
t=variables(N=100).time;
Δt=variables(N=100).step;
s=variables(N=100).InetrpolationDegree # returns 1
Additional Note
Keep in mind that you can also use Base.@kwdef
rather than @with_kw
.
答案2
得分: 0
你的问题似乎是你在括号[]
中包裹了你的范围对象,这会将其转换为一组范围的矢量,这可能不是你实际想要的结果。将字段签名更改为:
time::Vector{<:AbstractRange}=[a:step:b]
可以消除错误,但会带来一些不幸的副作用。首先,现在你有一组范围,而不仅仅是一个普通的范围。其次,该字段现在是抽象类型,这对性能不利。
我建议以下两种替代方案:
修复类型签名并移除括号:
@with_kw mutable struct Variables
InterpolationDegree::Int = 1
a::Float32 = 0.0f0
b::Float32 = 15.0f0
N::Int = 100
step::Float32 = (b-a)/N
Time::StepRangeLen{Float32,Float64,Float64,Int64} = (a:step:b)
end
或者,收集向量并修复签名:
@with_kw mutable struct Variables
InterpolationDegree::Int = 1
a::Float32 = 0.0f0
b::Float32 = 15.0f0
N::Int = 100
step::Float32 = (b-a)/N
Time::Vector{Float32} = collect(a:step:b)
end
如果可能的话,我更喜欢第一种替代方案,因为它使用轻量级范围,而不是浪费内存的Vector
,特别是对于长时间间隔。
另外两点注意:
- 按照惯例,类型名称应该大写:
Variables
,而不是variables
。 - 你确定你的结构体需要是
mutable
吗?不可变的结构体性能更好,可以更安全,避免意外的变更。
英文:
Your problem appears to be that you are wrapping your range-object in brackets, []
. That turns it into a Vector of ranges, which may not be what you actually want. Changing the field signature to
time::Vector{<:AbstractRange}=[a:step:b]
removes the error but has some unfortunate side effects. Firstly, you now have a vector of ranges, instead of just a plain range. Secondly, the field is now abstractly typed, which is bad for performance.
I suggest these two alternatives instead:
Fix the type signature and remove the brackets:
@with_kw mutable struct Variables
InterpolationDegree::Int = 1 # this field was mis-spelled
a::Float32 = 0.0f0 # using literal float syntax (not strictly necessary)
b::Float32 = 15.0f0
N::Int = 100
step::Float32 = (b-a)/N
Time::StepRangeLen{Float32,Float64,Float64,Int64} = (a:step:b)
end
Or, collect the vector and fix the signature:
@with_kw mutable struct Variables
InterpolationDegree::Int = 1
a::Float32 = 0.0f0
b::Float32 = 15.0f0
N::Int = 100
step::Float32 = (b-a)/N
Time::Vector{Float32} = collect(a:step:b)
end
I prefer the first alternative, if possible, since it uses a lightweight range, instead of a Vector
which wastes memory, especially for long time-intervals.
Two more remarks:
- By convention, type names should be capitalized:
Variables
, notvariables
. - Are you sure that your struct needs to be
mutable
? Immutable structs have better performance, and can be safer from accidental mutation.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论