Julia 具有有限数量或值的结构元素
我想创建一个Julia 具有有限数量或值的结构元素,julia,Julia,我想创建一个struct mutable struct myStruct id::string end 我确实希望id是一个字符串,但我希望它只接受3个值中的1个(例如“a”,“b”或“c”)。我的想法是,从理论上讲,这可以加快运营速度 关于提速,我说得对吗 这可能吗?如何实现 我不知道有什么方法可以让id成为String,同时限制它只有3个可能值中的一个,这样编译器就可以利用它 但是,如果可以选择离开字符串域,则有几种可能性。让我们尝试在这里对其中一些进行基准测试。为了便于示例,我们
struct
mutable struct myStruct
id::string
end
我确实希望id
是一个字符串,但我希望它只接受3个值中的1个(例如“a”
,“b”
或“c”
)。我的想法是,从理论上讲,这可以加快运营速度
我不知道有什么方法可以让
id
成为String
,同时限制它只有3个可能值中的一个,这样编译器就可以利用它
但是,如果可以选择离开字符串
域,则有几种可能性。让我们尝试在这里对其中一些进行基准测试。为了便于示例,我们假设此id
字段用于测试两个MyStruct
实例之间的相等性
这种类型的一种可能的(非常简单的)通用实现如下所示,其中参数T
确定用于id的类型
mutable struct MyType{T}
id :: T
end
# Two MyType instances are equal if their ids are equal
import Base.==
==(a::MyType{T}, b::MyType{T}) where {T} = (a.id == b.id)
现在让我们在各种情况下对等式运算符进行基准测试。首先,使用字符串作为标识符的基本情况:
julia> using BenchmarkTools
julia> a = MyType("apple")
MyType{String}("apple")
julia> b = MyType("banana")
MyType{String}("banana")
julia> @btime $a == $b
4.326 ns (0 allocations: 0 bytes)
false
我们希望整数更快,事实上是这样的:
julia> a = MyType(1)
MyType{Int64}(1)
julia> b = MyType(2)
MyType{Int64}(2)
julia> @btime $a == $b
1.882 ns (0 allocations: 0 bytes)
false
但也许API不那么方便。使用可能更具可读性(用户不必记住哪个值对应于“apple”)。它还可以防止使用任何未预定义的值,同时保持相同的性能:
julia> @enum Fruit begin
apple
banana
end
julia> a = MyType(apple)
MyType{Fruit}(apple)
julia> b = MyType(banana)
MyType{Fruit}(banana)
julia> @btime $a == $b
1.816 ns (0 allocations: 0 bytes)
false
julia> a = MyType(:apple)
MyType{Symbol}(:apple)
julia> b = MyType(:banana)
MyType{Symbol}(:banana)
julia> @btime $a == $b
1.883 ns (0 allocations: 0 bytes)
false
可能值得考虑的最后一个选项是用于密钥,它保留(IMO)可用性和性能:
julia> @enum Fruit begin
apple
banana
end
julia> a = MyType(apple)
MyType{Fruit}(apple)
julia> b = MyType(banana)
MyType{Fruit}(banana)
julia> @btime $a == $b
1.816 ns (0 allocations: 0 bytes)
false
julia> a = MyType(:apple)
MyType{Symbol}(:apple)
julia> b = MyType(:banana)
MyType{Symbol}(:banana)
julia> @btime $a == $b
1.883 ns (0 allocations: 0 bytes)
false
没有任何东西可以阻止任何人构建非法值,例如MyStruct(:cheddar)
,但它非常适合处理字符串的上下文。例如,如果您在工作流中的某个位置以字符串形式获取id,则可以在构建MyStruct
实例之前轻松地将其转换为符号:
julia> id = "apple"
"apple"
julia> a = MyType(Symbol(id))
MyType{Symbol}(:apple)
使用朱莉娅的打字系统!不需要外部库
abstract type Fruit end
struct Apple <: Fruit end
struct Banana <: Fruit end
struct Coconut <: Fruit end
struct MyType{T<:Fruit}
#could be some fields here...
end
a = MyType{Apple}()
a2 = MyType{Apple}()
b = MyType{Banana}()
编辑
对问题的回答@Cameron Bieganek
你对什么时候定义更合理有什么意见或指导吗 手动输入单例类型,以及何时使用
枚举更有意义
我个人的看法如下:
- 每当编译时已知类型值时,始终使用单例类型
- 只要在编译时已知一小组类型(符合小联合的条件),就使用单例时间
- 如果您计划根据类型实现不同的处理,请使用单例类型-广播将比一系列if语句更快
- 在设计API(您自己的Julia包)时,请使用单例类型,因为您可以使用Julia的文档功能
- 当运行时生成大量值(例如
String
s)并且您计划对它们进行相等比较时,请使用Symbol
s。很好的例子是解析一个CSV文件,其中列包含标称值李>
在其他情况下,考虑使用<代码> EnUM <代码> >或<代码>符号< /代码> s -使用代码可读性作为标准。李>
听起来像是枚举
在语义上更合适。我不知道是否会有性能上的差异。嗯,这听起来是一种可能的方式。你能详细解释一下并给出答案吗?你对手工定义单例类型和使用Enum
更合理有什么意见或指导吗?@Cameron Bieganek谢谢你的提问。我试着回答:-)回答得好,谢谢!这已经包含在您的“其他案例”中,但我可能会更明确地补充一点,当您计划存储一个值集合时,枚举或符号允许在具体类型的容器中进行存储,因此可能是首选。@CameronBieganek我认为单例类型在您准备(de)时更有意义序列化枚举。我不知道从包含名称的字符串或符号构造枚举大小写的好方法。我想这可能是一个有趣的问题。当然,我们可以通过元编程找到一些想法。