Create an enum from a group of related constants in Go - enums

What is preferred (or right) way to group large number of related constants in the Go language? For example C# and C++ both have enum for this.

const?
const (
pi = 3.14
foo = 42
bar = "hello"
)

There are two options, depending on how the constants will be used.
The first is to create a new type based on int, and declare your constants using this new type, e.g.:
type MyFlag int
const (
Foo MyFlag = 1
Bar
)
Foo and Bar will have type MyFlag. If you want to extract the int value back from a MyFlag, you need a type coersion:
var i int = int( Bar )
If this is inconvenient, use newacct's suggestion of a bare const block:
const (
Foo = 1
Bar = 2
)
Foo and Bar are perfect constants that can be assigned to int, float, etc.
This is covered in Effective Go in the Constants section. See also the discussion of the iota keyword for auto-assignment of values like C/C++.

My closest approach to enums is to declare constants as a type. At least you have some type-safety which is the major perk of an enum type.
type PoiType string
const (
Camping PoiType = "Camping"
Eatery PoiType = "Eatery"
Viewpoint PoiType = "Viewpoint"
)

It depends on what do you want to achieve by this grouping. Go allows grouping with the following braces syntax:
const (
c0 = 123
c1 = 67.23
c2 = "string"
)
Which just adds nice visual block for a programmer (editors allow to fold it), but does nothing for a compiler (you can not specify a name for a block).
The only thing that depends on this block is the iota constant declaration in Go (which is pretty handy for enums). It allows you to create auto increments easily (way more than just auto increments: more on this in the link).
For example this:
const (
c0 = 3 + 5 * iota
c1
c2
)
will create constants c0 = 3 (3 + 5 * 0), c1 = 8 (3 + 5 * 1) and c2 = 13 (3 + 5 * 2).

Related

F# record: ref vs mutable field

While refactoring my F# code, I found a record with a field of type bool ref:
type MyType =
{
Enabled : bool ref
// other, irrelevant fields here
}
I decided to try changing it to a mutable field instead
// Refactored version
type MyType =
{
mutable Enabled : bool
// other fields unchanged
}
Also, I applied all the changes required to make the code compile (i.e. changing := to <-, removing incr and decr functions, etc).
I noticed that after the changes some of the unit tests started to fail.
As the code is pretty large, I can't really see what exactly changed.
Is there a significant difference in implementation of the two that could change the behavior of my program?
Yes, there is a difference. Refs are first-class values, while mutable variables are a language construct.
Or, from a different perspective, you might say that ref cells are passed by reference, while mutable variables are passed by value.
Consider this:
type T = { mutable x : int }
type U = { y : int ref }
let t = { x = 5 }
let u = { y = ref 5 }
let mutable xx = t.x
xx <- 10
printfn "%d" t.x // Prints 5
let mutable yy = u.y
yy := 10
printfn "%d" !u.y // Prints 10
This happens because xx is a completely new mutable variable, unrelated to t.x, so that mutating xx has no effect on x.
But yy is a reference to the exact same ref cell as u.y, so that pushing a new value into that cell while referring to it via yy has the same effect as if referring to it via u.y.
If you "copy" a ref, the copy ends up pointing to the same ref, but if you copy a mutable variable, only its value gets copied.
You have the difference not because one is first-value, passed by reference/value or other things. It's because a ref is just a container (class) on its own.
The difference is more obvious when you implement a ref by yourself. You could do it like this:
type Reference<'a> = {
mutable Value: 'a
}
Now look at both definitions.
type MyTypeA = {
mutable Enabled: bool
}
type MyTypeB = {
Enabled: Reference<bool>
}
MyTypeA has a Enabled field that can be directly changed or with other word is mutable.
On the other-side you have MyTypeB that is theoretically immutable but has a Enabled that reference to a mutable class.
The Enabled from MyTypeB just reference to an object that is mutable like the millions of other classes in .NET. From the above type definitions, you can create objects like these.
let t = { MyTypeA.Enabled = true }
let u = { MyTypeB.Enabled = { Value = true }}
Creating the types makes it more obvious, that the first is a mutable field, and the second contains an object with a mutable field.
You find the implementation of ref in FSharp.Core/prim-types.fs it looks like this:
[<DebuggerDisplay("{contents}")>]
[<StructuralEquality; StructuralComparison>]
[<CompiledName("FSharpRef`1")>]
type Ref<'T> =
{
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
mutable contents: 'T }
member x.Value
with get() = x.contents
and set v = x.contents <- v
and 'T ref = Ref<'T>
The ref keyword in F# is just the built-in way to create such a pre-defined mutable Reference object, instead that you create your own type for this. And it has some benefits that it works well whenever you need to pass byref, in or out values in .NET. So you should use ref. But you also can use a mutable for this. For example, both code examples do the same.
With a reference
let parsed =
let result = ref 0
match System.Int32.TryParse("1234", result) with
| true -> result.Value
| false -> result.Value
With a mutable
let parsed =
let mutable result = 0
match System.Int32.TryParse("1234", &result) with
| true -> result
| false -> result
In both examples you get a 1234 as an int parsed. But the first example will create a FSharpRef and pass it to Int32.TryParse while the second example creates a field or variable and passes it with out to Int32.TryParse

How to fix 'constant x oveflows byte' error in go?

Hello I am trying to make a byte slice with constants but I get the constant x overflows byte error.
Here are my constants:
const(
Starttrame1 = 0x10A
Starttrame2 = 0x10B
Starttrame3 = 0X10C
Starttrame4 = 0X10D
Starttrame5 = 0X10E
Starttrame6 = 0x10F
)
and here is how I declare my slice:
var startValues = [6]byte{Starttrame1,Starttrame2,Startrame3,Starttrame4,Starttrame5,Starttrame6}
Everytime I build I get the constant 266 overflows byte. How should I declare my constants in order to fix this?
In Go, byte is an alias for uint8, which is the set of all unsigned 8-bit integers (0..255, both inclusive), see Spec: Numeric types. Which means a value of 0x10A = 266 cannot be stored in a value of type byte.
If you need to store those constants, use a different type, e.g. uint16:
const (
Starttrame1 = 0x10A
Starttrame2 = 0x10B
Starttrame3 = 0X10C
Starttrame4 = 0X10D
Starttrame5 = 0X10E
Starttrame6 = 0x10F
)
var data = [...]uint16{
Starttrame1, Starttrame2, Starttrame3, Starttrame4, Starttrame5, Starttrame6,
}
Try it on the Go Playground.

How to Initialize Variable to Maximum Value

I am trying to figure out how to initialize a variable in VBScript to its maximum value.
For example, in C++, I would do something like:
double x = MAX_DOUBLE;
I am not sure how to do this in VBScript.
UPDATE
For now, I have defined the variable myself as constant value in the global scope of the script. I am not sure if this is the most elegant way of doing this. Is there a built-in variable I can use?
Const MAX_DOUBLE = CDbl(1.79769313486232e307)
Const MIN_DOUBLE = CDbl(-1.79769313486232e307)
I've never found the limits described on MSDN to be accurate for many of the VBScript data types. For example, the Currency type gives me an overflow for anything > XXX.5625, even though the docs say it should go to XXX.5808. Same thing for Double. The docs say the max should be 1.79769313486232e308 but that final 2 in the mantissa causes an overflow. These are the values I've used in the past:
Const MIN_BYTE = 0
Const MAX_BYTE = 255
Const MIN_INTEGER = -32768
Const MAX_INTEGER = 32767
Const MIN_LONG = -2147483648
Const MAX_LONG = 2147483647
Const MIN_SINGLE = -3.402823e38
Const MAX_SINGLE = 3.402823e38
Const MIN_DOUBLE = -1.79769313486231e308
Const MAX_DOUBLE = 1.79769313486231e308
Const MIN_CURRENCY = -922337203685477.5625
Const MAX_CURRENCY = 922337203685477.5625
Const MIN_DATE = #100/1/1#
Const MAX_DATE = #9999/12/31#
Because VBScript uses Variants, however, note that you may not get the type you expect when assigning a "max" (or min) value to a variable. For example:
b = MAX_BYTE ' Actually type Integer
s = MAX_SINGLE ' Actually type Double
c = MAX_CURRENCY ' Actually type Double
If you want to ensure you're getting the proper data type in return, you'll need to explicitly cast:
b = CByte(MAX_BYTE) ' Type Byte
s = CSng(MAX_SINGLE) ' Type Single
c = CCur(MAX_CURRENCY) ' Type Currency

Golang: declare a single constant

Which is the preferred way to declare a single constant in Go?
1)
const myConst
2)
const (
myConst
)
Both ways are accepted by gofmt. Both ways are found in stdlib, though 1) is used more.
The second form is mainly for grouping several constant declarations.
If you have only one constant, the first form is enough.
for instance archive/tar/reader.go:
const maxNanoSecondIntSize = 9
But in archive/zip/struct.go:
// Compression methods.
const (
Store uint16 = 0
Deflate uint16 = 8
)
That doesn't mean you have to group all constants in one const (): when you have constants initialized by iota (successive integer), each block counts.
See for instance cmd/yacc/yacc.go
// flags for state generation
const (
DONE = iota
MUSTDO
MUSTLOOKAHEAD
)
// flags for a rule having an action, and being reduced
const (
ACTFLAG = 1 << (iota + 2)
REDFLAG
)
dalu adds in the comments:
it can also be done with import, type, var, and more than once.
It is true, but you will find iota only use in a constant declaration, and that would force you to define multiple const () blocks if you need multiple sets of consecutive integer constants.

GOLANG "Namespaced" enums?

I understand that the idiomatic way to create an enum in GO is as follows:
type topicStatus int
const (
registered topicStatus = iota
active
inactive
pending-removal
removed
)
but if I have another "enum" that wants to "reuse" a name, I get an error:
type hotelVisit int
const (
registered hotelVisit = iota
checked-in
checked-out
)
Here, if I try this, I cannot differentiate between topicStatus.registered and hotelVisit.registered as "registered" was previously used - is there a way to "namespace" the "enum" names?
Polluting the namespace with numerous common word lower case identifiers that are likely to cause naming conflicts isn't something I'd consider idiomatic Go. Same goes for creating packages just to hold a handful of constant declarations.
I'd probably do something like this:
type topicStatus int
const (
tsRegistered topicStatus = iota
tsActive
tsInactive
tsPendingRemoval
tsRemoved
)
type hotelVisit int
const (
hvRegistered hotelVisit = iota
hvCheckedIn
hvCheckedOut
)
Now you can declare and initialize with ts := tsPendingRemoval. Clear and concise with little risk of naming conflicts.
One workaround is to use an anonymous struct to define a namespace.
type TopicStatusType int
const (
registered topicStatus = iota
active
...
)
var TopicStatus = struct{
Registered TopicStatusType
Active TopicStatusType
...
}{
Registered: registered,
Active: active,
...
}
Create a new package for each of the enums you want to define. This means creating a sub-directory with a go file the has "package topicStatus" with the const definition inside (sub-directory name is the same as the package name).
Remember all the constants defined must be upper case so they are exportable.
Do the same for "hotelVisit" and whatever you need.
Your program will import these packages and then use them as needed: hotelVisit.Registered, topicStatus.Registered.
You can do like this:
var JobRunPhaseConstants = struct {
QUEUE_PRE_EXEC int
JOB_PRE_EXEC int
JOB_RUN int
JOB_POST_EXEC int
QUEUE_POST_EXEC int
}{
QUEUE_PRE_EXEC: 1,
JOB_PRE_EXEC: 2,
JOB_RUN: 3,
JOB_POST_EXEC: 4,
QUEUE_POST_EXEC: 5,
}
// usage example
var a = JobRunPhaseConstants.JOB_RUN

Resources