I want to create a struct
mutable struct myStruct
id::string
end
I do want id
to be a string, but I want it to take only 1 of 3 values (e.g. "a"
, "b"
or "c"
). My idea is that could theoretically speed up operations.
I don't know of any way to let id
be a String
, while constraining it to only have only one of 3 possible values in such a way that the compiler could take advantage of it.
However, if leaving the String
domain is an option, you have a few possibilities. Let's try and benchmark some of them here. For the sake of the example, let's assume that this id
field is used to test the equality between two MyStruct
instances.
A possible (very minimalistic) generic implementation of such a type would be the following, where parameter T
determines the type used for the 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)
Now let's benchmark the equality operator in various cases. First, the base case using strings as identifiers:
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
We would expect integers to be faster, and this is indeed the case:
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
But perhaps the API is less convenient that way. Using an enumerated type might more readable (users don't have to remember which value conrresponds to "apple"). It also prevents using any value that was not predefined, while keeping the same performance:
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
A final option that might be worth considering is to use symbols for keys, which preserves (IMO) the useability as well as the performance:
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
Nothing prevents anyone from building an illegal value such as MyStruct(:cheddar)
, but it fits nicely in a context where strings are manipulated. For example, if you get the id as a string somewhere in your workflow, you can easily convert it to a symbol before constructing the MyStruct
instance:
julia> id = "apple"
"apple"
julia> a = MyType(Symbol(id))
MyType{Symbol}(:apple)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With