Oh binary enums

What a nice incomplete idea…

I tried to do Const TestValue As UInt64 = -1 And Not TestEnum.SomeValue and I get told the enum does not define NOT. Um… ok fine.

Const TestValue As UInt64 = -1 Xor TestEnum.SomeValue

The compiler error is:

“This is a constant. Its value can’t be changed.”

Absolutely brilliant.

however this would look better

#If TestEnum.SomeValue = 111
  Const TestValue As UInt64 = -1 and not 111
#Else
  Const TestValue As UInt64 = -1
#EndIf

System.DebugLog TestValue.ToString

That block of code is really good at eliminating the point of using constants.

seems for xojo are enums not constants, it can not be mixed with other constants

the issue at you first example is i not see direct what value is .SomeValue

How did your solution turn out?

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.

seems the compiler see the type enum for some reason and not integer of the items.

alternative to a constant is a function with return, it protect the original very well :slight_smile:
(if someone see the same issue.)

Could it be your expression is a victim of precedence of operators ?

Consider breaking you line in two parts :

Const TestValue As UInt64 = -1 and And Not TestEnum.SomeValue

The first one is a constant that can’t be submited to the second one.

Maybe this would work :

Const TestValue As UInt64 = (-1 And Not TestEnum.SomeValue)

This way the contents of the () is evaluated first and the assigned to the constant.

I hate being bitten by precedence, and don’t want to have to remember it, so I use () to force the order of evaluation !

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.

That appears to be the point.

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.

this can be compiled but i find illogical because MyValue is integer and just a part of the enum.

Const a As Window1.MyEnum = MyEnum.MyValue
Var i as Integer = CType(a, Integer)
System.DebugLog(i.ToString)