Technology Temerity

Tutorial – Constants

This tutorial covers one of the most basic concepts of programming/scripting: User defined constants. It is meant for beginning coders and OpenBOR script writers. Upon completion, you should understand all of the following:

  • The definition of “Constant” in computer science (programming) as opposed to other uses of the term (such as mathematics).
  • How constants work in relation to other types of identifiers.
  • Where and how to apply constants.
  • Use of constants within the OpenBOR scripting engine.

Constants vs. Literals & Variables

To fully comprehend why constants are useful it is imperative to understand what a constant really is, especially compared to variables and literals. Literals are of particular note because it is very easy to confuse literals with constants. In the field of computer science, variables, constants and literals are usually defined as follows (Rao, 2017):

  • Variable: A variable is a storage location and an associated identifier which contains some known or unknown quantity or information, a value.
  • Constant: A constant is an identifier with an associated value that the program can not normally modify.
  • Literal: A literal is a notation for representing a fixed value.

Note the unfortunate caveat: “usually”. This is because some languages (C in particular) refer to both literals and constants as “constants” (Constants, 2020). They are then differentiated as “literal constants” and “symbolic constants” respectively. In programing circles, numeric literals are also called “magic numbers” (Definition of constants and magic numbers 2001). To avoid confusion between them we will henceforth only use the references “literal” and “constant”.

In practical terms, you may think of variables as named values that you can modify, constants as named values that you can’t modify and literals as values that mean exactly what they say. The question is how do these definitions and meanings apply in real world programming. To find out let’s start with variables and literals using this example polynomial:

i+3 = y

Applying our definitions above, there are two variables (i, y) and a single literal (3) in play:

  • i represents some number that can be whatever we want.
  • y is the sum result.
  • 3 is just three – it’s a literal value.

Now observe as we translate our equation into some code and see it in action:

for (i=0; i<10; i++) 
{ 
     y = i+3; print("Value: %i/n", y); 
}

What this snippet does is fairly straight forward (also useless, but I digress). First, we assign variable i a value of zero. Then we increment i by one in a loop until it is no longer less than ten. At each pass we assign y the sum of i + 3 and print the result, producing the following output:

3
4
5
6
7
8
9
10
11
12

Observe how our literal value 3 worked in relation to the variables surrounding it. Note the number 10 is also a literal, but for simplicity let’s just worry about 3. We could run this loop to infinity and it will always add i + 3 and assign the result to y. The variables i and y are continuously modified while 3 never changes. Easy enough yes? Remember:

Literals are static values written directly into source code; they “literally” mean what they say. Variables are IDs which are assigned values that can be (and usually are) modified while the program executes.

Now what would happen if we need to calculate our equation again, only subtracting 3 rather than adding? As an example, we’ll make a copy of our loop with a minor modification and run both in sequence.

for (i=0; i<10; i++)
{
	y = i+3;
	print("Value: %i/n", Y);
}

for (i=0; i<10; i++)
{
	y = i-3);
	print("Value: %i/n", Y);
}

This time we are not concerned with output. What does matter is our literal 3 and how we use it twice in succession. No problem thus far. But suppose later we need to substitute 3 with 5? Just edit the code and be done right? With examples like this, of course! Unfortunately real world coding is not so simple. Consider a real script or program. Even a something simple like some of the scripts powering this website may comprise several pages of code. For perspective, the OpenBOR engine contains ~600K lines of source code. Some of the largest applications can number in the millions. Now imagine trying to locate and edit every instance of 3. Or worse, trying to locate specific instances of 3, and leaving the rest alone. Copy/paste operations are effectively impossible. Hand editing is time prohibitive and error prone. This is where constants are so valuable. Let’s look at our example once again, with a little something extra added.

#define SOMENUM 3

for (i=0; i<10; i++)
{
	y = i+SOMENUM;
	print("Value: %i/n", y);
}

for (i=0; i<10; i++)
{
	y = i-SOMENUM;
	print("Value: %i/n", y);
}

As you’ve no doubt guessed, this and the previous example produce identical results. The difference is we no longer rely on a literal 3. Instead, this line creates a constant identified as SUMNUM and assigns it the value of 3:

#define SOMENUM 3

Just as i represents a loop counter value, SUMNUM represents the number 3. But unlike i and Y, SUMNUM can never change while the program is running. It maintains a constant value, hence the name. Effectively we have given a potentially VERY common value (3) its own unique identification. Attaching an identification to values that never change is an extra step that may seem silly at first, but in the long run actually saves you time. It is almost universally considered best practice (Recommended C Style and Coding Standards 2000).

  • There is no need to modify the code in multiple places. If we want to substitute our constant value for something else, we merely change the #define. Depending on scope of the program, this can range from being a simple time saver to enabling adjustments that are otherwise untenable or virtually impossible.
  • You may give constants nearly any imaginable label. That in turn enables creation of organized naming conventions for cleaner, more human readable code. This means superior design malleability, greater run time stability, and easier debugging when anomalies do occur.
  • It is possible to write programs with configuration blocks for simplistic modification of basic behavior and quick porting to other hardware platforms.
  • Separation of code and content! Why write a formula that only adds 2+2 when X+Y can perform the same task with infinite re-usability?

How To Use Constants In Your Code

Using constants is amazingly simple, but like any programming technique also sometimes mercurial. Every coding environment will have its own set of operators, methods, capabilities, and quirks. I will be focusing mainly on the the C based scripting engine of OpenBOR. A cursory Google search should provide all the instruction you need for other tools of choice.

OpenBOR

OpenBOR’s scripting engine is a C derivative and supports the define directive for constants. A define comprises three parts:

  1. Definition: Always “#define”.
  2. Identification: This is the name of your constant.
  3. Token: The value. This is what the computer will interpret whenever the constant is encountered in code.
#define SOME_IDENTIFICATION somevalue

Don’t worry about memory or CPU resources. The define directive is prepossessed, meaning the application handles it on start up. In other words, constants have no memory or run-time CPU cost.

General Tips

Naming Conventions

Decide on a naming convention before you start writing code. You will want names that are unique enough to avoid conflict while remaining reasonably succinct. Common practice is to use all caps for the identifier, with an underscore separator between each segment. The segments themselves should maintain Big Endian order.

#define BOVINAE_BISON			"Bison"	// Best in the west!
#define BOVINAE_BOS				"Cow"	// It's what's for dinner.
#define SIZE_LARGE				16		// Full meal.
#define SIZE_MEDIUM				12		// Light snack.
#define SIZE_SMALL				10		// For the kiddies.
#define TEMP_DONE_MAX			100		// Mmmmummm, that's the stuff!
#define TEMP_DONE_MIN			71		// Nice and brown.
#define TEMP_MEDIUM_MAX			65		// Little cold, but not bad.
#define TEMP_MEDIUM_MIN			60		// In a hurry?
#define TEMP_MEDIUM_WELL_MAX	69		// Not too shabby.
#define TEMP_MEDIUM_WELL_MIN	65		// Add some Worcestershire and we'll talk.
#define TEMP_RARE_MAX			55		// Somebody call a blood bank.
#define TEMP_RARE_MIN			52		// Moo!

Note the larger group of Subfamily appears first, followed by Genus. We follow a similar convention for cut size and cooking temperature. Who’s in the mood for a SIZE_LARGE BOVINAE_BOS TEMP_WELL_MAX?

Text File Use

In OpenBOR, any constants available in a model’s animation script are also available in the model text. This means constants are usable inside of @script tags or as function arguments in @cmd tags.

Reading this function call is very difficult unless the creator has a perfect memory, and it’s impossible for anyone else….

@cmd set_bind_state 7 1

…but with constants, the creator can instantly identify what the function call should do, and if need be can easily find related calls with a text search. Other readers may not understand right away, but they can probably get a rough idea and debug from context:

@cmd set_bind_state BIND_STATE_FACE_DOWN DIRECTION_RIGHT

When/Where Should Constants Be Used?

One of the more common questions involving constants is “When should I use them?” The answer is “whenever possible.” As a more usable interpretation of “whenever possible”, consider the following:

  • Is the value static?
  • Will you use the value more than once?
  • Does the value lack infinite range and variation?

If the value fits these criteria, then replace it with a constant. Remember, defined constants in OpenBOR are “free”, they don’t consume any more resources than the literal values they replace.

Final Words

I hope this helps you to understand how simple, elegant and useful constants can be, and I would encourage you to make full use of them in your own projects. Lastly, please feel free to leave comments below with any questions or opinions you may have, and I will see to them in short order. If you have any questions about the OpenBOR engine, stop by at ChronoCrash and we’ll be glad to help.

Thanks for reading!
DC

References

C Constants. (2020). https://www.w3schools.in/c-tutorial/constants/.

Def. (2001). Definition of constants and magic numbers. https://www.inf.unibz.it/~calvanese/teaching/05-06-ip/lecture-notes/uni04/node17.html.

Rao, S. (2017, January 27). Informit. InformIT. https://www.informit.com/articles/article.aspx?p=2755729.

Def. (2001). Definition of constants and magic numbers. https://www.inf.unibz.it/~calvanese/teaching/05-06-ip/lecture-notes/uni04/node17.html.


Originally published 2013-02-04.

Author: Damon Caskey

Hello all, Damon Caskey here - the esteemed owner of this little slice of cyberspace. Welcome!

Leave a Reply