You might have noticed something else that’s new about the active mode structure of a sketch, that being the usage of the void keyword preceding both the setup() and draw() functions. The keyword void is used for defining functions that do not return a value, all other user defined functions must return a value of a certain type of data. The setup() and draw() functions differ significantly from their roots in the C/C++ main() function in that they are not intended to return a value of any type of data to the main program, the mandatory usage of the void keyword ensures this. We’ll have a look at user defined functions in more detail later.
The process of assigning a type to data is known as datatyping. There are many different types of data within Processing we have already had a look at some of the categories that the different types of data within Processing can be broken down into, but what exactly are these different types of data and how do they assist us in programming?
One of the datatypes we’re already familiar with is the PImage datatype. We know that if we want to use a bitmap image in our sketch we must first assign it to the object we instantiated from PImage. That new object that we have then created has inherited all of the properties of the PImage datatype amongst which is the ability to resize the image, get information about the pixels that make up the image and what the alpha and color values of each pixel making up the image is. We did not have to tell Processing what a pixel is or how we would like to use it, these definitions already exist predetermined within the PImage class and other Processing API features, and will resemble a body of code that exists somewhere on your computer (probably in the location you installed the PDE). Now that we have a new object instantiated from the PImage class it has inherited all of the properties that define that particular type of data, in other words the new object we have created has been datatyped as PImage.
But in order to understand what is really going on here we need to look a little deeper…
Variables are common to most programming languages as they provide us with a means of storing data within the memory of a computer without having to know the process the computer has taken to store that data and where exactly within the computers memory that data has been stored. This provides us with a convenient method for accessing data, without having to understand the complexities of manual memory management as might be the case in lower level languages. Lets have a look at how variables play a part in helping us store data.
Using variables is pretty straight forward and can be thought of as a two step process,
1.) Declaration and 2.) Assignment.
The second step we are already familiar with, which could imply that you might have already used variables in your previous sketches, and this is in fact correct. You have used both steps of variable creation in your previous programs as variable assignment relies on declaration.
Declaration is the process of giving the data you are representing in your program a name, and is a process that involves datatyping (preformed by the programmer) and memory allocation (performed automatically in most higher level languages). So lets have a look at a declaration in the following statement:
This is known as a form of variable declaration, you might at this point be thinking “I thought this is supposed to be object instantiation (as it has previously been referred to)?” You’d be right on both counts in this particular case because there are in fact two different things going on here. Firstly the PImage class defines all objects that are instantiated from it, by whatever code that makes up it’s class body, and because PImage is specific to Processing’s API and not something that exists readily within other programming languages referring to the preceding statement as object instantiation reveals the underlying structure of what is going on in Processing when compared with other programing languages. However, since PImage is a class defined within Processing’s API and can be used for datatyping the preceding statement can also be viewed as declarative, as such img can be referred to as an object variable. In contrast lets have a look at a simpler declaration that does not involve a Processing specific datatype, which can make the process of defining variables easier to grasp:
The keyword int in this statement is used to datatype a variable with the properties of type integer.
Integers are primitive datatypes that must be whole numbers, such as 0, 5, -1, 2430 and so on. They cannot have a decimal value. All we are doing at this stage is giving the variable a name, that being myVar, we have not given the variable a value yet the value would effectively be an integer, and associating the variable with a value is specifically what assignment is for.
In the above statement we have declared a variable called myVar and datatyped it as an int. So when we want to use the variable and the data associated with it in our program we can simply refer to it by it’s name for example:
However this is getting ahead of ourselves a little, as you might remember one of the main reasons we use variables is so that we can associate data with them through the process of assignment. In the previous example we have declared a variable but not given it a value, so lets restructure the example to be more meaningful:
int myVar; //Declaration
myVar = 5; //Assignment
println(myVar); //Prints 5
In the second line of the above code listing we have used assignment to associate the numerical integer value of 5 with our variable, and in the third line we have put the variable to work by getting println() to read it’s value back to us. You might also notice that variables are never placed between double quotes, like the literal strings we have been using with the println() function up till now.
What makes variables so special is that we can get them to store any value that is valid to it’s datatype, change this value then re-use it in another statement with the new value, without the help of variables a simple task like this would be very impractical. This is particularly useful as we never have to know what address the variable we are using has in memory, Processing takes care of that for us.
Here’s an example of the changing (or “variable”) nature of a variable:
int x; //declaration
x = 5; //assignment x is now 5
x = x + x; //assignment expression x is now 10
println(x); //Prints 10
The value you assign to a variable can be changed when ever you instruct your program to do so, often through use of the assignment operator. As a result in the previous example although we started with the variable we called x having a value of 5 assigned to it in the second statement, in the next line we added it’s current value of 5 to itself then reassigned that new value of 5 + 5 (on the right of the assignment operator) back to itself (on the left of the assignment operator), making x equal 10. Using this simple method we have represented two different values of 5 and 10 with only one variable, x. That does not mean that x could be either 5 or 10 it simply means that at the start of the program x was 5 and by the end of the program x ended up being 10. By having one variable that can be used to represent many different values we can save on memory as, at any given time, that variable can only have one value associated with it, meaning that if a new value is assigned to it like in our previous example that new value will replace the old one and so on. Not only does this make our program run more efficiently but it also makes keeping track of the representations of the different data in your program more manageable.