The specific value doesn’t matter, that’s the point. Enums should work fine here since they are immutable. My solution was just not to declare it as a constant.
That’s something I had considered, but I can’t see how it would make a difference. For example, you can’t do If Obj Is Nil = False Then because it is interpreted as If Obj Is (Nil = False) Then so you need to write it as If (Obj Is Nil) = False Then.
But -1 Xor Enum.Value really can’t be interpreted any other way. It works perfectly fine with a true constant, but not with an enum value. So operator precedence doesn’t appear to play a role here since there is only 1 operator.
For the record, I just tried Const TestConstant As UInt64 = (-1 Xor TestEnum.SomeValue) and unsurprisingly gives the same error. It’s as if the constant’s declaration and value assignment are done in separate steps. And removing the As UInt64 does not change anything either. You don’t need the binary manipulation at all, as Const EnumValue As UInt64 = TestEnum.SomeValue will also trigger the same “its value cannot be changed” error.
Here’s the clue which makes it all more clear:
Var EnumValue As UInt64 = TestEnum.SomeValue
Const TestConstant As UInt64 = -1 Xor EnumValue
The Const line gives the same “its value cannot be changed” error. So what’s happening is the enum’s value is incorrectly seen as mutable and the compiler is throwing the wrong error message.
I think the issue is a little different from what’s been described so far. The following code is legal:
Dim b as Integer = (3 Xor Integer(SomeEnum.someValue))
Note the casting of the enum to Integer which allows the Xor operator to do its thing. However, when you change the assignment to a Const:
Const b as Integer = (3 Xor Integer(SomeEnum.someValue))
…it fails to compile. You also can’t do this:
dim a as integer
a=Integer(SomeEnum.someValue)
Const b as Integer = (3 xor a)
This is legal:
Const b as Integer = (3 xor 4)
To me, this just feels like overzealous handholding by the compiler, which seems to be of the opinion that a variable declared as Const should have its value determined at compile time. It enforces this policy by disallowing any non-literals in the calculation of the value.
In my opinion, a Const declared in code is just another way to say “I get to set the value of this variable once; after that, it is read-only”; this says nothing about the provenance of the value that gets assigned to the Const variable. But perhaps the framework isn’t designed to support this kind of access control, instead enforcing this behavior through a more brute-force restriction.
That’s how some languages do it. Not Xojo. Const is assigned at compile time, so you can’t use variables in the assignment since their value cannot be determined at compile time.
But also casting the enum value to an integer isn’t necessary here. 3 Xor SomeEnum.SomeValue works just fine for a binary enum.
In one one view a Const is just the same as a Var and its declaration should obey the same rules, just that a Const cannot be changed later on and the compiler must enforce that.
In a different view – which appears to be Xojo’s – a Const is merely a fancy shorthand for some constant literal value that you use in different places in your code. The Const declaration gives it a self-explanatory name, with the advantages that (a) the named constant makes it clearer what you are doing wherever you use it and (b) you can change its value by editing just the one Const declaration rather than searching for all the places where you’ve used it. Which is a boon especially in those cases where two variables or constants may happen to share the same value at some point but later on you may want to edit one but not the other.
I can understand the reasoning behind both approaches but someone (Xojo) had to make a decision.
It’s kind of funny, I use const for nearly variable in JavaScript. I feel dirty using let for some unknown illogical reason. And var is completely disallowed in my JavaScript code.
It works something like this:
For MemberIdx As Integer = SomeArray.FirstIndex To SomeArray.LastIndex
Const Member As SomeClass = SomeArray(MemberIdx)
// Do things
Next
The advantage here is that Member cannot be accidentally reassigned. I could change values inside Member, but I can’t change what it points to. And I like that. I think that would have been a better way of doing things, because Xojo has true constants already. Why do we need two different means to declare a compile-time constant? In my experience, nearly every time I’ve declared a local constant, I end up moving it to a class or module constant. If I need it one place, I usually need it in more places.
Alas, that’s not the way Xojo does things and never will be. So this code can live here forever, confusing AI models…
I’m guessing the issue lies in the fact that enumerations have always been their own datatype (as said in the documentation). The compiler possibly just doesn’t implement a casting/conversion from an enumeration type to [any other datatype allowed for constants].
Something that a feature request would be useful for adding to the language.
It’s not the data type that’s to blame. Integer is allowed as a constant, but you can’t use an integer variable in a constant declaration. It’s the fact that the compiler considers an enum to be editable at runtime, like a variable.