Hello,
I defined a baremodule
baremodule Return
const INVALID_CMD = 0x00
const CMD_FINISHED = 0x01
end
I would like to get a Dict from this module with keys being 0x00 and 0x01 (and more …)
How can I achieve this task?
Kind regards
Hello,
I defined a baremodule
baremodule Return
const INVALID_CMD = 0x00
const CMD_FINISHED = 0x01
end
I would like to get a Dict from this module with keys being 0x00 and 0x01 (and more …)
How can I achieve this task?
Kind regards
You can do this with names
and getfield
, but using a module in this way is very uncommon and probably not a good idea. What are you trying to do, and why do you need a module to store these constants?
I sometimes overload enumerate
to list all the constants in a baremodule:
import Base.enumerate
function enumerate(::Type{T}, mod) where T
n = names(mod,true)
v = map(x->getfield(mod,x),n)
filter(v->typeof(v)==T,v)
end
julia> enumerate(UInt8,Return)
2-element Array{Any,1}:
0x01
0x00
But you could use an enum too.
I noticed this kind of usage in
What I like is that I need to do Return.CMD_FINISHED
to access 0x01 constant
With Enum,
julia> @enum ReturnE::UInt8 INVALID_CMD = 0x00 CMD_FINISHED = 0x01
julia> ReturnE
Enum ReturnE:
INVALID_CMD = 0
CMD_FINISHED = 1
One problem, is that despite I defined type of UInt8
, Enum doesn’t seem to keep a track of it (see 0, 1, instead of 0x00 and 0x01).
Moreover I can access directly to INVALID_CMD
without preceding with ReturnE
which is not something I like
With Enum, accessing to a given key with a value can be done using ReturnE[0x01][1]
and I get CMD_FINISHED::ReturnE = 1
What I don’t like with enumerate approach is that we get an Array of Any.
I just need to be able to get :CMD_FINISHED
from 0x01
Ah, I see. Your UInt8
declaration in the @enum
is working, it’s just that Julia is displaying the value by converting it to a plain Int
. I’m honestly not sure why that’s done, but it’s possible to prove that your enum values really are UInt8s:
julia> @enum ReturnE::UInt8 INVALID_CMD = 0x00 CMD_FINISHED = 0x01
julia> sizeof(CMD_FINISHED)
1
julia> Base.Enums.basetype(typeof(CMD_FINISHED))
UInt8
sizeof
gives the size in bytes, so CMD_FINISHED
is stored in exactly 1 byte.
It’s perfectly reasonable to want a namespace for your enum. How about the following:
julia> module Return
export ReturnCodes
@enum ReturnCodes::UInt8 INVALID_CMD=0x00 CMD_FINISHED=0x01
end
Return
julia> sizeof(Return.CMD_FINISHED)
1
julia> Return.ReturnCodes[0x01]
1-element Array{Return.ReturnCodes,1}:
CMD_FINISHED
Thanks a lot @rdeits!
Maybe we should open an issue about Enum display with UInt8?
I also wonder how to get CMD_FINISHED
value as UInt8 without specifying type.
Is Base.Enums.basetype(Return.ReturnCodes)(Return.CMD_FINISHED)
the simplest approach?
===
About baremodule approach, thanks to @jonathanBieler suggestion I implemented 2 functions
function getSymbols(mod::Module, value)
vct = Vector{Symbol}()
for n in names(mod, true)
if n != Symbol(mod)
v = getfield(mod, n)
if v == value
push!(vct, n)
end
end
end
vct
end
function getDict(mod::Module, t::Type)
d = Dict{Symbol,t}()
for n in names(mod, true)
if n != Symbol(mod)
v = getfield(mod, n)
if !haskey(d, n)
d[n] = v
else
error("$n is not unique - $(d[n]) $v")
end
end
end
d
end
I posted it here but I think I will in fact use the Enum approach (bracketed version) as it also insure that values are unique at creation.
module Return
@enum(ReturnCodes::UInt8,
CMD_FINISHED = 0x01,
INVALID_CMD = 0x00,
)
function code(val)
Symbol(Return.ReturnCodes[val][1])
end
end
PS: edit 2018-06-06 Julia 0.7 now supports begin/end for enum
https://github.com/JuliaLang/julia/blame/master/NEWS.md#L44
https://github.com/JuliaLang/julia/pull/25424
Issue opened at https://github.com/JuliaLang/julia/issues/27025 about display of Enum with UInt8
I’ve also found at times that name-spaced enumerations would be nice. Mainly because otherwise the items seem a bit polluting on the name-space and also are a hassle to export (or rather not). I like @rdeits’s solution (but is the export
needed?).
Nope, export
isn’t necessary. I just thought it might be convenient.
SuperEnum
https://github.com/kindlychung/SuperEnum.jl
provides a macro to define automatically enum inside module.