Tuesday, 11 March 2014

Hashes

Hashes are another kind of variable and in my opinion they are pretty similar to arrays. They are indexed, the same as arrays, but instead of being indexed with a number, they are indexed with a user defined string and this index is called a key. This gives us a key/value pair. A good example of this is a dictionary (an actual book dictionary) where the word is the key and the definition is the value.
The value of a hash can be any type of variable - it can be a number, a string, another hash, an array or even a variable name...

You can tell that you are looking at a hash if it's prefixed by a % sigil. I think it makes more sense to have a hash (#) as the sigil if you're going to call it a hash but never mind, a hash is already reserved for comments.
%hash
A hash can actually be modelled by using arrays like this:
1.   my @french_words = ("bonjour", "au revoir", "merci");
2. my $hello = 0;
3. my $goodbye = 1;
4. my $thank_you = 2;
5. print $french_words[$goodbye];
But it looks really strange and clumsy and who wants to bother with all that when a hash works perfectly well?


Declaring and assigning

Again there are lots and lots and lots of ways of declaring and assigning a hash.
You can declare the hash and then add one element at a time:
1.   my %hash;
2. $hash{"up"} = "down";
3. $hash{"top"} = "bottom";
4. $hash{"charm"} = "strange";
What does this all mean? - First, I've declared the hash in line 1 using the % sigil and in lines 2 to 4 I've added individual elements to it. The individual elements of the hash are prefixed with a $ because they hold an individual items - a scalar. Then comes the hash name followed by the key you want in curly brackets, the key can be any string. You then assign this to what you want as a value, more on what you can assign to it later.

or you can declare everything all together:
1. my %hash = ("up", "down", "top", "bottom", "charm", "strange");
Here I've assigned a list to the hash. The list needs to have an even amount of elements because consecutive elements are paired up into key/value pairs. If you have an odd amount of elements, the last value is going to be undef. In this hash the key/value pairs are up-down, top-bottom and charm-strange.

This version is more readable:
1. %hash = ("up" => "down", "top" => "bottom", "charm" => "strange");
so you can see which are the keys and which are the values more easily.

Or you can do the even more readable and, I think, preferred by the perl community:
1.   my %hash = (
2.     up => "down",
3.     top => "bottom",
4.     charm => "strange",
5. );
This is exactly the same as the method above it, only spaced out to be clearer.
And of course if I was coding properly all of the "fat commas" (these things "=>") as they're called would all line up, but this blog thing won't let me do that!

Also the thing about the comma at the end of line 4 applies here as well - you don't need it but it's a good idea to put it there to prevent unnecessary line changes if extra elements are added to the end of the hash. See my array post for more details.

You may have noticed that in my last code example, I didn't put quotes around the keys. You don't actually need them because the key is always going to be a string and perl knows this. You only need to put quotes if you're including whitespace or other special characters such as "-", so in these cases you need to explicitly stringify (make into a string) the key by using the quotes.


Printing
As far as I can see, when you print out a hash, they don't necessarily come out in the same order that you declared them in but they do print out in the same order every time you print them. This is because they are printed out in their internal order, which can't be relied on because it will change if you add or delete key/values pairs but will stay the same otherwise. It also changes with the version of perl you're using because the way the keys are ordered has changed several times.

This is one easy way to print a hash that involves a for loop, which I haven't covered yet. But for the moment, just trust me that it works. This will print out all of the key/value pairs with nice spacing:
1.   print "$_ $hash{$_}\n" for (keys %hash);
writing print %hash does the same thing but squashes everything together

Note The trick I showed to print arrays in my last post doesn't work at all here. If you type print "%hash\n" you will get "%hash" printed to the screen.


Accessing and using elements of the hash

Deleting Elements
Hashes are not fixed sizes so you can add to them and delete from them as you like. Unlike with arrays, when you delete an element from a hash, there won't be and undefs unless you only get rid of the key or only the value. This means you don't need to worry about having any gaps in your hash.

To delete a key/value pair, you can do this:
1.   delete $hash{"up"};
Note that you only have to specify the key and the value will be automatically found and deleted as well. I guess this would be useful in cases where you might not know the value. Maybe.

Adding Elements
This is exactly the same as when you're first creating the hash and adding one element at a time. If you want to add more elements later on, you just do exactly the same thing:
1.   $hash{key} = "value";
There is no need to use "my" because the hash has already been declared, you're just adding to an existing variable.

What can I put in my hash?
You don't always have to have the value as a string, it could be a number or a variable containing a string or a number:
1.  $hash{key} = $value;
Or an array or a hash:
1.  $hash{key} = \@values;
Be very careful when doing this, you have to make sure that you give it a reference to an array or a reference to a hash rather than the thing itself. I'll go more into these later on but this is how to do it for now. You either put a backslash in front if you're using a variable as above or, if you're putting the hash or array straight in, you need to use [] for arrays and {} for hashes.

The reason for doing this is because, if you don't, the array or hash will just become part of the original hash you've created, new keys and values will be created. Hopefully this example will explain what I mean:

1.  my %address = ('Line One' => "5 The Street", 'Town/City' => "London", 'Post Code' => "W15 9QT");
2.
3.my %person = (
4.    Name => "Emma", 
5.    Age => 23,
6.    Height => "164cm",
7.    Address => \%address,
8.    );

The hash drawn out will now look something like this (as you would expect):

Name => Emma
Age => 23
Height => 164 cm
Address => (
    Line One => 5 The Street
    Town/City => London
    Post Code => W15 9QT
)

I created a script that would run the code above but I took out the backslash on line 7. Here is what came out:

Name => Emma
Age => 23
Height => 164cm
Address => Post Code
W15 9QT => Line One
5 The Street => Town/City
London => undef

This is clearly not what we wanted, instead of a hash within a hash, there is only one big hash.

And also, if you were reading carefully before, you'll see that I said each element of the hash contains a scalar. Arrays and hashes aren't scalars but their references are so this is another reason why you must make any hashes or arrays into references if you don't want them to be

Moral of the story, make sure you use a reference if you're going to do a hash within a hash or an array within a hash!!!


Editing Elements
If you want change a value, you just assign it to the key and the old value will be overwritten:
1.  $hash{key} = "new value";
If the key doesn't already exist, a new key/value pair is created so you need to be careful with the spelling of the key when you want to edit a key that's already there or you could end up with the original key and a misspelled version of the key.

Changing the key of a key/value pair is a lot more tricky. On looking up ways to change it, I think the best way to do it is to delete the key/value pair and start again. You can change it, but it's a lot more code than just deleting and starting again.

Duplication
Duplicate keys are not allowed although duplicate values are. If there are duplicate keys declared, only the last one will be acknowledged and the rest will be disregarded. So if we did something like this:
1.   my %hash = (
2.     "Name" => "Fred",
3.     "Weight" => "70kg",
4.     "Height" => "190cm",
5.     "Weight" => "75kg",
6. );
7. print $hash{Weight};
The answer printed will be 75kg.

Can you get the element key from the value?
Kind of. With some coding. There's unfortunately no easy trick here. Also values don't have to be unique so you could end up with the wrong key.

Adding hashes together

This is really easy, assuming you already have two hashes that already have things in them (%hash_one and %hash_two), you can just do this:
1.  %hash_three = (%hash_one, %hash_two);
Easy!

Exists - is the key already in the hash?
This is useful because duplicate keys aren't really allowed so you can check first if the key already exists before you add a new key/value pair.

And finally...
To get a list of all the keys in the hash:
print keys(%hash);
And to get a list of all the values in the hash - you guessed it:
print values(%hash);

Wednesday, 19 February 2014

How does sort actually work?

I talked about sort in my last post, but I started to read more about it and got wondering, how does it actually work?

You can use sort to order lists numerically or lexically. To sort lexically you use the cmp operator within the curly braces:
1.   sort{$a cmp $b}("please", "sort", "this", "list");
and for sorting numerically, you use the <=> operator:
1.   sort{$a <=> $b}(13,2,8,1,3,1,5,21);
What I think this means is that $a and $b refer to the two strings or numbers that are being compared when the algorithm is run. The letter "a" comes before the letter "b" in the alphabet and $a is put in front of $b in the code which means that words beginning with a letter that comes before other words in the alphabet should be sorted in front of those other words. Hopefully this all makes sense and is actually accurate.

Perl 5.6 and earlier used the quicksort algorithm and perl 5.7 and onwards, uses the merge sort algorithm. On wikipedia (http://en.wikipedia.org/wiki/Merge_sort) there's a pretty good animation at the top of the page that shows how merge sort works.

Quicksort - perl 5.6 and earlier

I remember learning this at school and uni and thinking it's pretty cool but also wondering what it was used for. We had to write a program in Java that carried out a quicksort. I should have just submitted one line of perl code...

Quicksort is a divide and conquer algorithm and there are different variations of it based on which position you choose for the pivot (explanation very soon) but I couldn't find out which version was used for sort in perl. So for simplicity, and because it's how I was taught, I'm going to choose the pivot and the value in the middle of the list.

So we have a list of numbers (assuming we're using numbers and sorting them in ascending numerical order) and the value in the centre of the list is the pivot. All numbers lower than the pivot are put on the left of this pivot and all numbers higher are put on the right. This creates three different lists - numbers lower than the pivot, numbers higher than the pivot and the pivot itself. The pivot list is one element long and is considered sorted so now we need to sort the other two lists in the same way. For each list, a pivot is chosen and again, lower numbers go on the left and higher numbers go on the right. This now creates seven lists. This continues until you have lists containing only one element, putting these lists all together will give one sorted list. Here's an example (please feel free to skip the example if you already know how it works or if it doesn't interest you!):

(4,2,9,6,5,1,8,7,3)

The number in the centre of the list is the pivot.

Starting from the left, numbers lower than 5 are put into one list to the left and numbers higher than 5 are put into another list on the right. 4 is taken out first giving:

(4)  (2,9,6,5,1,8,7,3)

Then 2 is taken out and put in the list on the left:

(4,2) (9,6,5,1,8,7,3)

Then 9:

(4,2) (6,5,1,8,7,3) (9)

This is repeated, excluding the pivot until we have three list with the pivot on its own:

(4,2,1,3)  (5)  (9,6,8,7)

Pivots are now chosen from any lists with more than one element. I think this time, as there is no real middle element, I will use the (n+1)/2th element.

(4,2,1,3)  (5)  (9,6,8,7)

The same is applied starting with the first list - all element lower than one go on the left and all numbers higher than one go on the right:

(1) (4,2,3) (5) (9,6,8,7)

The same is applied to the other list:

(1) (4,2,3) (5) (6,7) (8) (9)

Again, pivots are picked for the lists with more than one element:

(1) (4,2,3) (5) (6,7) (8) (9)

And the same sorting is applied giving:

(1) (2) (3,4) (5) (6) (7) (8) (9)

Then the final list that contains more than one element is sorted:

(1) (2) (3) (4) (5) (6) (7) (8) (9)

Put this all together and you have a sorted list:

(1,2,3,4,5,6,7,8,9)

Merge Sort - perl 5.7 onwards

So all of that wasn't entirely relevant for those of you that have upgraded your perl version since 2002 because from perl 5.6, the sort function has used the merge sort algorithm.

Merge sort is also a divide and conquer algorithm. It works by splitting up the list into individual elements. Each element is compared to its neighbour and (again assuming we're using numbers and sorting them in ascending numerical order) the smaller number is put on the left and the larger on the right. Then the next set of pairs are compared and so on until the end of the list. Then these sorted pair are compared to each other and ordered to make groups of four. Then these sorted groups are compared to the other groups and this is repeated until the whole list is in one big, sorted group. Hopefully this example will make all this clearer (again, feel free to skip this bit if you don't really care!):

Say we have a list of:

(4,2,6,5,1,8,7,3)

We then split it into sublists which contain one individual element. This means we have eight sublists of single elements:

(4)  (2)  (6)  (5)  (1)  (8)  (7)  (3)

Then we compare the elements to their next door neighbour. First will be (4) and (2). 2 is smaller so goes in front of 4 and we have our first sorted pair of (2,4)

(2,4)  (6)  (5)  (1)  (8)  (7)  (3)

The smallest sublists are always compared first so we compare the next two single element sublists - (6) and (5) giving:

(2,4)  (5,6)  (1)  (8)  (7)  (3)

This is continued until all the sublists contain two sorted elements:

(2,4)  (5,6),  (1,8)  (7)  (3)

(2,4)  (5,6)  (1,8)  (3,7)

Then the pairs are compared to each other starting with (2,4) and (5,6) and always comparing the first element of each list. First 2 and 5 are compared, 2 is smaller so is taken out to make a new list:

(2,4)  (5,6)  (1,8)  (3,7)

(2

Then the first elements of the target sublists are compared so 4 and 5, 4 is smaller so is taken out making:

(4)  (5,6)  (1,8)  (3,7)

(2,4

Then there's only one target sublist left so elements are taken out one by one from the front:

(5,6)  (1,8)  (3,7)

(2,4,5

(6)  (1,8)  (3,7)

(2,4,5,6)

And finally:

(2,4,5,6) (1,8) (3,7)

Then the pairs (1,8) and (7,3) are compared in the same way with intermediate steps:

(2,4,5,6) (1,8) (3,7)

(1

(2,4,5,6) (8) (3,7)

(1,3

(2,4,5,6) (8) (7)

(1,3,7

(2,4,5,6) (8)

(1,3,7,8)

Giving us two sorted lists of:

(2,4,5,6) (1,3,7,8)

Finally these two sublists are compared in the same way to give one sorted list of

(1,2,3,4,5,6,7,8)

If that doesn't make sense, again, I highly recommend looking at the animation on the wikipedia page.


Why was quicksort ditched in favour of merge sort?

According to the perl docs, the quicksort algorithm used was unstable because it can become quadratic. What????

A stable sort preserves the order of list elements that compare equal so maybe the quicksort algorithm kept sorting list items that were exactly the same as each other, which made the run time and complexity higher.

The run time of both of these algorithms comes out as O(n log n) when averaged over all arrays of length n. However, because quicksort does not always preserve the order of equal elements, its run time can become O(n^2) - which is a quadratic because the n is squared. This behaviour doesn't happen with merge sort so quicksort was replaced.

The perl docs do say that for "some inputs" on "some platforms" the original quicksort was faster, but no other information is given - I'm not sure which inputs or which platforms, but I'm sure that these are a minority. Also as an extra note, I think that 99.99% of the time, any time or performance differences will not be large enough to be noticeable anyway.



Thursday, 13 February 2014

Lists, Lists, Lists

List or Array?

I've written a post about arrays and kind of glossed over the array/list distinction. Some people got back to me about the fact that I hadn't really talked about lists at all so here I'm going to try to explore what a list is and how it differs from an array.

A list is just what it sounds like - a number of items separated by a comma.
An array is assigned a list, it contains the list but it isn't the list itself. I don't think that you can access elements in a list via index numbers unless you explicitly do something to make it be treated like an array.

So this is a list:

("apples", "bananas", "cherries", 45, 360)

We can assign it to an array:
1.   my @array = ("apples", "bananas", "cherries", 45, 360);
And this is an array:

@array

In my post about arrays, I showed a way to get the number of elements in an array using scalar(@arr) and I also talked about using scalar on a list but I didn't explain it very well.

So if we have:
1.   my @arr = ("this", "is", "a", "list);
The difference between
1.   print scalar(@arr);
and
1.   print scalar("this", "is", "a", "list");

is that the first one is giving the scalar value of an array, which is the number of elements in the array (4) and the second one is giving the scalar value of a list, which is the value of the last element ("list"). Two very similar statements, but giving you very different results - I think this is very strange behaviour.


Note To prevent you from having to type loads of quotes in your list, which I know for me definitely slows down my typing and results in a lot of pressing the wrong keys, you can do this:

my @arr = ("this", "is", "a", "list");

my @arr = qw(this is a list);

Much quicker and qw stands for "quote word". The only problem is that the space between the words means that the words are separate list items so if you want to include a space in one of your list items, you're going to have to use quotes.

You can do lots of things with lists and here are some of them.

The following only work on an array so you have to assign your list to an array first.

Pop

This takes the last element from the array and gives it to what you are assigning it to.

my @arr = (1,2,3,4,5);
my $val = pop(@arr);

$val has the value 5 and @arr is now (1,2,3,4)

Push

This one is kind of the opposite of pop. Instead of taking away from the end of the array, you add an element on to the end of it.

my @arr = (1,2,3,4,5);
push (@arr, "x");

@arr is now (1,2,3,4,5,"x")

Shift

This is a different opposite of pop. Instead of taking the last element of the list and assigning it to a value, you take the first element.

my @arr = (1,2,3,4,5);
my $val = shift(@arr);

$val has the value 1 and @arr is now (2,3,4,5)

Unshift

This is the opposite of shift and push. An element is added to the front of the array.

my @arr = (1,2,3,4,5);
unshift (@arr, "x");

@arr is now ("x",1,2,3,4,5)


I think this little table sums up everything above:

Beginning or end of array Add or remove element
Pop End Remove
Push End Add
Shift Beginning Remove
Unshift Beginning Add


Sort

You can also sort your lists using the sort function:

Lexically: 

If sort is used by itself with no parameters, it will sort the list in standard string comparison order, which basically means alphabetical order. You can either use sort directly on a list as I have below or you can assign the list to an array and use sort on the array. Just type "sort" before the list or before the array.
1.   my @arr = sort("hello", "my", "name", "is", "emma");
2.   print "@arr\n";
When this the above code is run, it will come out with:
emma hello is my name
This can also be written as
sort {$a cmp $b} ("hello", "my", "name", "is" "emma"); 
Note
If you have words beginning with capital letters, these will always be sorted in front of lower cased words, even if they come after the lower cased word alphabetically.

To sort the words into a backwards order just reverse the a and b:
sort {$b cmp $a} ("hello", "my", "name", "is" "emma");

Numerically:
1.   my @arr = sort{$a<=>$b}(7,9,4,2,8);
2.   print "@arr\n";
To sort numerically, you use the <=> operator rather than cmp and you still use $a and $b to represent the two numbers being sorted in the alogorithm. When the above code is run, you will get:
(2,4,7,8,9)
Again, to sort backwards, you reverse the a and b:
1.   my @arr = sort{$b<=>$a}(7,9,4,2,8);
2.   print "@arr\n";
 This will print:
(9,8,7,4,2) 
List mapping
 
The map function is used to transform lists element-wise. You can go through each element of a list and perform a function on it and a new list of the new values will be created.

To do the map function, you say that you want to put the result into a new array (@new_numbers in the code below), then you type an equals sing, then the word "map" and then what you want to do to each element in curly brackets. $_ refers to each individual element, kind of like x in a mathematical equation. In the code below what I've said is to take each element and times that element by two. Then you type the list that you want to perform the operation on - you can either write the list out or give an array like I've done.
1.   my @numbers = (1,2,3,4,5);
2.   my @new_numbers = map{$_*2}@numbers;
3.   print "@new_numbers\n";
Which will print:
2 4 6 8 10
You can also apply map to text:

1.   my @text = ("this", "is", "a", "list");
2.   my @new_text = map{$_.":"}@text;
3.   print "@new_text\n";
Which will print:
this: is: a: list:

Grep

Grep is similar to sort, although instead of applying a change to each element, it evaluates the result of the operation and if the result is true, the original value will be put into a new list, if the result is false, the original value will be filtered out.

Again you start with the array you want your new list to be put into (@multiples_of_two), then an equals sign and then the evaluation you want is put in curly braces. The evaluation must create an answer that is either true or false. Then you give the list, either written out as a list or as an array. The code below goes through the list of 1-10 and puts the multiples of two into a new list.

1.   my @numbers = (1,2,3,4,5,6,7,8,9,10);
2.   my @multiples_of_two = grep{$_%2==0}@numbers;
3.   print "@multiples_of_two\n";
This will print:
(2,4,6,8,10)

Thursday, 6 February 2014

@arr = ("my", "first", "array");

Now, I know that arrays are a huge topic so I can't possibly fit everything into one post or you'll all get really bored. So here are some of what I think are the key points to understanding arrays, enjoy...

Arrays are just data structures where we can store a list of singular things (scalars) in a specific order. They are like lists, but each element is associated with an incremental number and you can access each of these elements using its associated number. In fact you can assign a list to an array variable name and it will turn into an array.

Arrays are really important, in my clearly expert opinion, because sometimes we need to store things in a specific order and sometimes it makes sense to store a lot of scalars together in one place. You can also do a lot of things with them like iterate through each entry or do the same thing to each entry and put it into a new array. That kind of thing. You can store numbers and strings and arrays and other scalars and mixtures of all of those things into the elements of the array. Here's how:

You can tell you are looking at an array if the variable name is prefixed by an @ sign so for example:
@myarray
I've recently found out that punctuation marks in front of variables in perl are actually called sigils so I may or may not start calling them that from now on.


Declaring and Assigning

As with many things (nearly everything) in perl, arrays can be declared and assigned in different ways:

These two ways show the whole array being created in one go - a list is created and then this list is assigned to the array name:

1.   my @arr;
2. @arr = ("this", "is", "array", 1);

Note that strings are in quotes and numbers are not

or

1.   my @arr = ("this", "is", "array", 2);
Arrays can also be created one element at a time:

1.   my @arr;
2. $arr[0] = "this";
3. $arr[1] = "is";
4. $arr[2] = "array";
5. $arr[3] = 3;

Note that the array index starts at 0 and also that when you assign something to the individual array positions, you use a $ sign (sigil!). This is because each array entry is a singular piece of data, and from my post about scalars, we know that singular pieces of data are stored in scalars and scalars are identified by a $ sign.

If you skip out element positions when you are creating an array like this:

1.   my @arr;
2. $arr[0] = "this array";
3. $arr[2] = "has";
4. $arr[5] = "some";
5. $arr[6] = "gaps";

When you print it out, you will get:

this array, undef, has, undef, undef, some, gaps


Accessing the elements

Once you've declared and assigned your array, you probably want to do things with it. You can access each element by referring to it's index number, remembering that it starts from 0. So for the array
1.   my @myarray = ("this", "array", "is", 6, "elements", "long");

To print the word "is", you need to use the $ sigil as it's a single piece of data, then the name of the array, then a 2 in square brackets because "is" is in the array with element index 2:

1.   print $myarray[2];

Tip

If you want to print out your whole array with a space in between each element, you need to write something like:

print "@array\n";

This interpolates all of the array elements into a string and by default, each element is separated by a space.

Length of Arrays

You can either use

scalar(@arr)

or

$#arr+1

The first one makes more sense and I think it's easier to understand. It just gives you the array as a scalar value which turns out to be the number of elements it contains. The second one gives you the index value of the last element in the array and because the index starts from 0, you have to +1 to get the number of elements.

There's something you need to be careful about within this topic and I think it's a bit of a red herring. If you write:
1.   print scalar(100, 300, 200);
The answer you will get is:
200
this is because it's giving us the value of the last item in the array. So watch out!

Iterating through arrays - this topic is a bit more complex and needs scary things like loops, which I'll cover later so I'm going to run away from it now...


Array of arrays

I think my brain is exploding at trying to visualise this. You can put as many arrays in arrays in arrays in arrays as you like and end up with a multi-dimensional mess. But as long as you can understand it and everyone reading your code can understand it, then everything is fine.

There are, again, many ways implement this. You can declare some arrays and then put all of these into one big array:
1. my @name1 = ("Emma", "Jane", "Howson", 23);
2. my @name2 = ("Willard", "Carroll", "Smith", 45);
3. my @name3 = ("Tyra", "Lynne", "Banks", 40);
4. my@name4 = ("Alecia", "Beth", "Moore", 34);
5. my@name5 = ("David", "Boreanaz", 44);
6.
7. my@perfectdinnerparty = (\@name1, \@name2, \@name3, \@name4, \@name5);
On line 7 you may have notice the backslashes before the @ sigils. This is to prevent one giant array being created where 23 is the 4th element in the array with an index of 3, "Willard" will then become the 5th element in the array with an index of 4 and "Carroll" will be the 6th element with an index of 5 etc. The backslashes actually turn the arrays into array refs, which I don't understand at the moment but I'll get to in a later post. All I know is they enable the structure of an array of arrays.

Or you can declare them all at once:
1.   my @perfectdinnerparty = (
2.     ["Emma", "Jane", "Howson", 23],
3.     ["Willard", "Carroll", "Smith", 45],
4.     ["Tyra", "Lynne", "Banks", 40],
5.     ["Alecia", "Beth", "Moore", 34],
6.     ["David", "Boreanaz", 44],
7. );

The outer brackets need to be parentheses () and the inner ones surrounding each array element need to be square brackets [] and these indicate that the contents are also an array ref.

Another note is that you need to put commas between each outer array element (so between each set of square brackets), but you don't need to put a comma after the last array entry (where it's highlighted). I think it's good practise to do this anyway because if you need to add another element (another square bracket set) to the array, you only need to alter one like of code.

Accessing elements in an array of arrays

The process is very similar to an array although there are two numbers in brackets to find the location of the element you need. So to get the string "Smith" from my perfectdinnerparty array, I would use:

1.   $perfectdinnerparty[1][2];

The first number is the index of the number of arrays in the super array and the second number is the index of the element in each array in square brackets.

Another note

$var and @var are two completely different variables and have nothing to do with each other. You can't access one by using the other one so it's probably best not to use the same variable name to avoid confusion. Another case of just because you can do it, doesn't mean you should.


As always, please correct me if I'm wrong with anything and any suggestions of how to find out more are welcome.

Tuesday, 28 January 2014

"Strings"

Strings

A string is basically any amount of characters in sequence including zero characters, which is known as the empty string. Similarly to numbers, the maximum size or length of a string is basically limited to your computer's memory, which is probably far larger than any real string you're going to work with.

These are all examples of strings:

"Hello"
""
"This is a string"
"This 1 is a 2 string 3 including 4 some 5 numbers 8907"
"27195"
"☆☘☺"
"مرحبا"

Perl has full support for unicode (basically any letter or symbol or number in any language you can think of), but if you're going to use characters out of the ASCII range in your program (so variable names and other bits of code that aren't in single quoted strings), you'll need to use the pragma

use utf8;

I think it doesn't use unicode by default for historical reasons so when Perl was written, there was only a need to use ASCII characters.


Quotes

Strings are surrounded by either single or double quotes or delimiters that imply quotes - more on these later. These quotes and delimiters are not part of the string itself, they just indicate that whatever is inside should be treated as a string.


What is the difference between having single and double quotes?

Single quotes
mean that whatever is in the quotes is represented literally so newline characters or any other control characters are not interpreted as control characters, they are just printed out literally:

print 'Hello everyone\n'

will print:
Hello everyone\n
which is probably not what you want to see in most cases.

The only character that is interpreted is the backslash. This is to enable you to use a single quote in a string. For example:

'I\'m a Perl programmer'

The backslash means that the quote doesn't end where the single quote is used as an apostrophe (if that makes sense). You can use a single backslash in your string if it isn't at the end of the string. If you do want a backslash at the end of a string, you need to put two in a row. I would say it is advisable to always use two backslashes in a row incase this kind of thing happens as two backslashes will always print just one.

'This string contains one backslash \\'
This will print:
This string contains one backslash \

Double quotes interpret special symbols so you can include all sorts of control characters as well as displaying characters through octal and hex representations. You can also embed other variables into the string.

my $name = "Emma\n";           # will print 'Emma' and then a newline
my $string = "Hello $name";   # will print 'Hello Emma'

Delimiters are useful if you want to use quotes inside your string are used by first typing 'q' for a single quoted string and 'qq' for a double quoted string. Then you type the character that you want to be the delimiter, then write out the string with no quotes and then add the delimiter character at the end.

I thought a delimiter could be any character, but I tried to use letters and numbers and they don't seem to work and anyway using these wouldn't be very advisable because it doesn't look very clear. It does work with any type of punctuation and it's usually useful to have it as a character that doesn't appear in your string because otherwise you have to use a backslash to escape your delimiter character and all this can start to look a bit confusing.
For example:

'Hello World!'
is equal to all of these: 
q(Hello World!)
q{Hello World!}
q.Hello World!.

"Hello World!"
is equal to all of these: 
qq/Hello World!/
qq[Hello World!]
qq?Hello World!?
I told a lie - you don't always use exactly the same character as you did to start the string. If you notice the brackets always start with a left bracket and end with a right one. Interestingly, you can use two close brackets but you can't use two open brackets. Maybe because if you open a bracket it expects a close bracket and gets very confused and upset if you don't give it one.

You can use punctuation marks like $, @ and % as delimiters. Also very inadvisable because these are used commonly to declare scalars, hashes and arrays and you don't want to confuse yourself or other poor people that have to look at your code.

String Manipulations

There are many many many things you can do with a string in Perl, far too many to list in this post. Some of the main ones and ones that I think would be useful are as follows:

Concatenation

To concatenate (join together) two or more strings you use the . operator.

my $string1 = "apple";
my $string2 = "pear";
my $string3 = "peach";
my $all = $string1.$string2.$string3;
print $all; 
This will print:
applepearpeach

You don't have to just concatenate variable names, you can also add in new strings:

print $string1.", ".$string2." and ".string3;

will print:
apple, pear and peach

Repetition

To repeat a string, you put the string in quotes, then x, then the number of times to repeat the string.

print 'Hello' x 5;

This will print:
HelloHelloHelloHelloHello

Interpolation

Interpolation means that you can include a variable in a string and if you put that string in double quotes, the value of the variable will be printed. You must use double quotes for interpolation, because if you use single quotes, the string will be printed literally and you will just see the variable name.

my $name = "Emma";
print "The variable \$name has the value $name";

This will print:
The variable $name has the value Emma


And that's the end of my very long post, congratulations if you've made it this far!

Wednesday, 22 January 2014

Numbers

Many different types of numbers can be represented in Perl. The good thing is that you don't have to specify what kind of number you are using as the interpreter can work it out for itself.


Integers

Integers consist of any whole number either with a sign or without:

1
0
2014
-365
7875493754977009

Perl allows you to add underscores to integers to make them easier for a human to read so for the last number in the list you can write:

7_875_493_754_977_009

This makes absolutely no difference to what the number is or how it is handled, it's just easier for our inferior mortal brains to comprehend.

There aren't really limits as to the highest and lowest integers that can be stored. The limits are basically subject to your computer's memory but I don't think in practise anyone really wants to use numbers that large. Also you will be sacrificing some precision when your numbers get that large and I think the reason for this is similar to why floating points are not entirely precise. Although I could be making that up.

So, on to floating points...


Floating Points

Floating points are numbers with a decimal point and also with or without a sign.
As with most programming languages, integers are (mostly) represented exactly but floating points are an approximation of what the decimal places are. It seems to me that this is because numbers are stored in binary and some fractions, for example a third, can only be expressed with an infinite binary representation. Seeing as computers do not have infinite memory, we have to chop off the end of the number and store the closest thing we have.
I think this level of precision is sufficient for most applications but I guess for research or anything scientific that requires precision, something else is going to be needed.

1.5
-23.45
550.0
-1.0
5.43e24
-5.2e28
-5e-12
6.34e-13

The 'e' in the middle of some of the numbers above mean that they are using the exponent. So 5.43e24 means 54.3 X 10^23 or 543 followed by 22 zeroes.


Non-decimal Integers

I always forget about these types of numbers, it makes me stop and remember that the only reason we count the way we do is because we have ten fingers and in a parallel world, eight-fingered martians are learning about this weird decimal way of counting.

I'm not really sure why anyone would use these in a real world application - maybe I'll see later on.

With non-decimal numbers, we have to indicate which type of numerical system we are using, otherwise they will just be treated as decimal numbers. The way to indicate these are really simple and not at all cumbersome:

Binary
0b1101110 - all binary numbers start with '0b'
Octal
0156 - all octal numbers start with a '0'
Hexadecimal
0x6e - all hex numbers start with '0x'

all the above amount to 110

These numbers can also be signed or unsigned.

Numeric Operators

Perl allows you to use operators on numbers so you can do calculations, these are the main ones:

+ addition
- subtraction
* multiplication
/ division - this will always give you the floating point value if the result of the division is not an integer
% modulus - the values are always reduced to integers first, for example 10.5 % 3.2 will be calculated using 10 % 3 where the answer will be 1
** exponentiation - for example 2**3 means 2^3 or two to the power of three where the answer will be 8

So now we can do things like:

my $sum = 24 + 12;
my $subtraction = 10.5 - 5.3;
my $exponentiation = $sum**$subtraction;

As always, please add comments to this or any other of my posts. I'm a beginner so I need feedback on anything I've written that's wrong and also any extra information or helpful links or anything else you can think of that will help me learn is appreciated.

Tuesday, 21 January 2014

my $scalar;

In most of the books I'm using, the first thing after all the set up and hello world stuff is scalars. This seems to be sensible to me because they're quite simple for a beginner to understand and seemingly fundamental to the Perl language.

From what I understand, scalars make up any singular piece of data - it's when Perl has one of something and often this will be a number or a string but not an array or hash or other complex data type. You can identify a scalar variable because it's prefixed by a $ sign so if you see a variable named:
"$something" 
you know that it contains a singular piece of data.


Unlike other programming languages (Java), Perl is not strongly typed and is intelligent enough to know that when you have typed a string in quotes, you want it to behave like a string and when you type a number, you want it to behave like a number.

This means there is no faffing around telling the interpreter what kind of variable you want when it can work it out for itself. All you need to do is tell it what you want the variable to be called and what you want in that variable. Simple

There are ways of giving the variable a number but wanting it to behave like a string and vice versa but these have to explicitly be done. The default is to treat whatever it is as what it looks like - which sounds very sensible to me but I think there could be some potential problems with this so I guess it needs to be kept in mind.



Declaring and assigning a scalar

There are two ways to declare and assign a scalar variable; you can either do it all in one go:

my $name = "Emma";

or declare and assign separately:

my $name;                    #This is declaring the scalar
$name = "Emma;"        #This is assigning it

This has basically said that there is a scalar variable called "name" and the value of this scalar is the string "Emma". The quotes just denote the beginning and the end of the string and won't actually be printed out. If you want to assign a number to a variable, you don't need to put the quotes but more on that later.


If we leave 'my' out and we have use strict turned on (which you should have!!), the program will fall to bits when you try to run it and complain at you with something that looks like this:

Global symbol "$name" requires explicit package name at declaration.pl line 5.
Execution of declaration.pl aborted due to compilation errors.

Not the friendliest of error messages, but I have seen worse. This error message could also mean that you've made a typo when writing a variable name. This will mean having different spellings between the declaration and any usage of it, which will make the interpreter cry.


So, now we know how to declare a scalar, the next question is what exactly can we store in these scalars? Posts to follow on numbers and strings...