Chapter 3. Variables and Types

This chapter will go over basic local variables and the type system. Topics covered will be declaring and assigning variables, types, and incremental unary operators.

3.1 - Local Variables

In programming, a variable is an identifier or word that represents some sort of value. This identifier can have it's value re-assigned or changed, and can be accessed wherever it is used in the variable scope (the extent in which the variable is recognized).

Variables are declared (created) using the assignment = binary operator. The left hand side of the operator is the name of the variable and the right hand side is the initial value. Let's create a simple program to create a new variable named x and give it the value of 7.

func main () {
    x = 7;
    println (x);
}

This code prints out the value 7, since the variable x is given the value 7. When the arguments for the println function are evaluated, the identifier x is accessed and the value 7 given to println instead.

Once a variable has been declared, it can be re-assigned to again. Take this program which shows how a variable can be changed.

func main () {
    x = 7;
    println (x); # prints 7
    x = 10;
    println (x); # prints 10
    println (x); # prints 10
    x = x - 1;
    println (x); # prints 9
}

The output of this code is:

7
10
10
9

The first two lines of main are something we should be comfortable with. The variable x is declared with the value of 7, then this value is printed out. From there, x is re-assigned to 10, which is printed out twice. After the two print statements you will notice a very interesting line of code, x = x - 1. What this does is first computes the right hand side of the assignment operator. x, which is currently 10, has 1 subtracted from it, which is 9, which is then assigned to x.

It is important to denote the difference between x = x - 1 and x - 1. Pay attention to this next program.

func main () {
    x = 15;
    println (x - 1); # prints 14, BUT x is still 15
    println (x);
    x = x - 2;
    println (x); # prints 13
    println (x + 3); # prints 16;
}

The output of this program is:

14
15
13
16

The first println call in main is told to print the result of x - 1, however this does NOT mean that x is equal to x - 1. x still holds it's value, as demonstrated by the next println. After that, x is set to the result of x - 2, which is 13.

3.1.1 Operators - Prefix Increment/Decrement

Recall earlier the line of code x = x - 1. This sort of statement has to be written frequently by programmers, oftentimes for looping purposes. There is a simplified way of writing this statement, called the incremental unary operators. There are four of these operators, the prefix incremental, prefix decremental, postfix incremental, and postfix decremental. Each of these operators either add or subtract 1 from the variable they operate on.

What separates the prefix operators from the postfix operators is the order that they return their value. Prefix operators assign their value to the variable, then return the value. Postfix operators assign their value but return the old value.

Here is a program showcasing the prefix operators.

func main () {
    x = 9;
    ++x;           # x is now 10
    println (x);   # prints 10
    println (++x); # x is now 11, prints 11
    println (x);   # prints 11
}

Output:

10
11
11

The first line assigns the initial value of 9 to the variable x. The next line increments x, giving it the value of 10, which is then printed out with the third line. The next println statement firsst increments and stores x, moving it up to 11, then prints that value out. The final println displays this unchanged number again.

3.1.2 Operators - Postfix Increment/Decrement

The complements to the prefix increment/decrement operators (as covered in 3.1.1) is the postfix set. These operators are just like the prefix set, except they appear after the identifier instead of before the identifier.

Postfix also differs from the prefix operators in how they return their values. Prefix operators preform the increment or decrement, then return that result. Prefix operators return the original value, then increment or decrement the variable.

Take the following program.

func main () {
    x = 13;
    x--;           # x is now 12
    println (x);   # prints 12
    println (x--); # prints 12, x is now 11
    println (x);   # prints 11
    println (x++); # prints 11, x is now 12
    println (x);   # prints 12

Output:

12
12
11
11
12

This program starts by declaring the variable x to 13. The next line decrements x, changing it's value to 12. It is important to note that since this line is not part of a statement, it would not matter if you used the postfix or prefix decrement operator to preform this action. Try it out yourself and you will see the output is still the same. The first println statement showcases the postfix operators. Even though x is being decremented, it still prints the last value of x, then preforms the decrementation, as shown by the next println. The fourth println displays the same value of x, but then increments it for the final println.

3.1.3 Variables - Naming

So far, the single local variable declared in the code examples has been x. In Hassium, variable names can be infinite in length as long as they follow a set of rules. Variable names must start with a letter or an _, and can include numbers after the first character. This means the variable connection4 is valid, but the variable 4thConnection is invalid, since it starts with a number.

Variable names must not include any symbols or be any reserved keywords (identifiers a programming language uses to detect statements). This means the variables apple&orange and func would be invalid and raise a compiler exception.

Since a variable cannot have a space character inside of it, variables that represent more than one words must take advantage of casing (how multiple words are represented in an identifier). There are four main styles of casing; PascalCase, camelCase, SNAKE_CASE, and lowercase. Which case you use depends on the type of identifier you are declaring. Hassium good practice dictates that local variables must be lowercase. This means if you wished to declare a local variable to represent customers served today, you would declare it is customersservedtoday. For classes, PascalCase must be in use. If you wanted to create a class for a restaurant customer, you would declare it as class RestaurantCustomer. For constants (unchanging variables), you would use SNAKE_CASE. To define a constant for hash length you would declare it as HASH_LENGTH.

3.2 - Types

In programming, each variable or datum used has at least one type (inheriting name representing the data). So far, the only types we have dealt with have been integers (whole numbers) and strings (series of characters). Types are used to ensure that the data you are operating on is of the proper type. For instance, if you wanted to add numbers together, you would want to make sure that the numbers being added are of an integer or float (decimal number) type. If they were are string or a bool (true or false) type, then the program would not work as expected.

Unlike most static languages like C# or Java, Hassium lets you assign different types to the same variable. Take this C# code for instance.

static void Main (string[] args) {
    int i = 8;
    i = 7; // Valid since 7 is also an int.
    i = "8"; // Will not compile, since "8" is a string.
}

Because i was declared as an int, all the values assigned to it thereafter must also be ints. When
writing in a dynamic language like Hassium however, this is not an issue.

func main () {
    i = 8;   # i is an int.
    i = 7;   # i is still an int.
    i = "8"; # i is now a string.
}

3.2.1 Operator - is

Hassium comes equipped with a type checking operator called the is operator. The is operator is a binary operator. The left side should be the variable or data we wish to type check and the right side should be the type your are checking against. The operator will return a bool true is the left side is of type right side, otherwise it will return false.

func main () {
    println ("Hai" is string);
    println (6 is string);
    a = 5.9;
    println (a is float);
    println (a is int);
    a = "Hai";
    println (a is string);
    println (a is float);
    println (a is object);
    println ("anything" is object);
}

Output:

true
false
true
false
true
false
true
true

The first two lines of the program are operating on direct data itself. "Hai" is of type string, so it returns true. 6 however, is not of type string, so it returns false. Then we have a variable named a declared to the float 5.9. a is of type float but not of type int. a is then redeclared to the string "Hai". a is now a string, but no longer a float. The last two lines of the program are extremely important. a is of type string, but also of type object. In Hassium, every single piece of data or element has the type object. It is the most generic type in Hassium.

3.2.2 Statement - Enforced Assignment

Even though Hassium does not require you to explicitly define types for variables the same way other programming languages do, it provides support for this style. This is called enforced assignment (assignment where types are explicitly given). The benefit to using this style is that it is clear to the reader what type a variable is, especially if the value of the assignment is a function call to another file. The syntax for enforced assignment is <type> <var> = <value>. If the value provided does match the declared type, a runtime exception will be thrown on that line.

func main () {
    int a = 9;       # 9 is an int, so this is okay.
    float b = 3.5;   # 3.5 is a float, so this is okay.
    bool c = "true"; # "true" is a string, this raises a runtime exception.
}

Output:

At location 4 : 21:
Expcted assignment type bool, got string! at:
func main ()

The output shows nothing for the first two lines, since they don't print out anything. However the third line has an error, we told c that it had to be a bool, but a string value was given instead. This raised a runtime exception (an error with a message that stops program execution), telling us about this assignment issue.

Chapter 3 - Exercises

For each exercise, have a program that displays a is bool, a is char, a is float, a is int, a is object, and a is string.

Exercise 3.1

a = 4;

Exercise 3.2

a = 5.2;

Exercise 3.3

a = "hello";

results matching ""

    No results matching ""