constants of objects in type not possible?

BlitzMax Forums/BlitzMax Programming/constants of objects in type not possible?

Tibit(Posted 2010) [#1]
This does not compile because "Constant initializers must be constant", while that is the very point of a const, if I cannot even set the value in the constructor then they are not possible to use for custom-types I'd assume? It confuses me if this where the case, it seems so basic or is there something stupid simple I have missed?

I'm simply using Globals instead though so no big problem, but still :)


Also as a side-note, it does appears that Globals are not initialized at program-start, so it would appear this code would be valid, but it is not:



Last edited 2010


ziggy(Posted 2010) [#2]
A constant can only have a constant value, you're using it to perform a function call, wich implies the value is unknown while the function is being executed, and this is the oposite of a constant, the value has to be known and immutable.


Warpy(Posted 2010) [#3]
Another explanation: Constants have to be number or string literals, ie 0.1234 or "hello". If you use the name of another variable, or a function call, then the compiler would have to go and look at that and check that it's constant. That's a very tricky problem (undecidable, in fact!) so the compiler just refuses to do it.

The upshot is, you can only have constants of number types or strings, not user-defined types.


H&K(Posted 2010) [#4]
What about this?
SuperStrict 

Type Car
Field ID:Int = 1
Global lastCar:Car = New Car

Method New()
ID = lastCar.ID +1
lastCar = Self
EndMethod
EndType

Local someCar:Car = New Car



Tibit(Posted 2010) [#5]
I thought constants only inferred that the value could not be set/get, but yeah never really considered that only applied to value-types (and they cannot be null in C# at least).

Also I remebered that in C# there is a keyword called readonly, that does just that, which I somehow thought was what const in blitzmax did, I also saw Color as a value type, which is it not ;)

H&K, I get the same null error with your example. When are they Global lastCar:Car = New Car called? Directly after the new() method?


Czar Flavius(Posted 2010) [#6]
C++ lets you use constants that way, but unfortunately you can't in BlitzMax. It's a double-edged sword though. If you start marking certain things as constant, you end up having to mark lots of things as constant, and if you change your mind, it causes you a real headache. This is because C++ enforces constantness really strongly. You can't pass a (non-simple-data) constant as a parameter to a function, unless that parameter is also marked as constant, and so on.

There are two main motivations for using constants. First of all, a compile-time constant is a bit faster than a local or global variable, so you do it for extra speed.

Secondly, it helps to prevent you from making mistakes. By marking something that shouldn't change as a constant, you can prevent yourself from accidently modifying it. Run-time constants are ordinary variables that are calculated at run-time (such as from a function call) and simply marked as "read-only".

A compile-time constant benefits from both areas. A run-time constant benefits from only the second area.

In BlitzMax, there are only compile-time constants. So numbers known at compile-time which won't change can be made into constants to get a tiny speed boost. (It's only tiny, so don't become paranoid about it) Run-time constants are not supported. This is why your Colour objects cannot be made constant. They are created at run-time, after the program has been compiled. Only values created at compile-time can be made constant.

There is one exception to this rule in BlitzMax - you cannot make a constant array. This is a bit of a shame, as an array whose values are known at compile-time (ie hard-coded) can become a compile-time constant and benefit from the speed increase.

For a run-time "constant" or constant array, your only choice is to make them Global variables and just remember never to modify them. For an object, if it's really important to you, you could have a "constant" field which can be set either on or off. If you don't access fields directly, and use "getter/setter" methods, you can check the status of this field at the beginning of a method that modifies the object, and refuse the operation if the object has been set to constant. Warning: this will slow things down, as an extra check has been made, and might make you waste time adding this "feature" to all your objects when it's not really necessary. Only use it if you super-really need to make something read-only and can't trust yourself not to forget.

I hope this clears things up for you and gives you a deeper understanding of the topic.

Last edited 2010

Last edited 2010


Tibit(Posted 2010) [#7]
Thanks for the extra info, interesting read indeed!

I was after the usability aspect only :)

It can really catch some awful errors, especially when you share code with others or when one app interact with another (network), exactly the same reason why I miss private in bmax, such things allows you to create code that are a bit more 'user-safe'


ziggy(Posted 2010) [#8]
There's a workarround for private, that consist on creating apublic field of a private type in a public type, and use the public type just as the visible interface for your private class. Sounds a bit weird at first, but if you want to see it in action, you can take a look to the TBitmapFont class in the fontmachine module. It works pretty well and allows a decen level of 'boxing'. It's a bit like wrapping blitzmax code, using blitzmax code, but it works.

Last edited 2010


Tibit(Posted 2010) [#9]
Haha yeah that was a creative work-around ziggy, maybe you could even reduce the type-name to just "_" to make the code even leaner. Personally I 'll stick with public fields and fix them when bmx2 is released instead :)


Czar Flavius(Posted 2010) [#10]
I prefix private fields with _ as a note not to use them outside the class. So long as you understand what it means, you can emulate the idea.