Main Content

Daisy the Cow and a Pint of Ginger Beer

Archive - Originally posted on "The Horse's Mouth" - 2008-10-21 19:40:16 - Graham Ellis

One of the trickiest aspects of learning for newcomers to programming is to know when to split out parts of their code into named blocks. Newcomers can easily see that it's a good idea - as it means that code can be tested in smaller chunks, and that code can be shared (reused) - but it's not always obvious just how the division / split should be done.

Here's a rule of thumb ... if you find yourself repeating something, then it's probably an excellent candidate to be a named block of code. Sometimes there's a counter-comment made - "Yes, but I have had to alter the copy so in the end the code isn't duplicated", to which I'll reply the places you have to alter the copy are telling you which parts of the named block of code are going to be passed in as parameters, or back as return values

From today's Perl course, here is an sample application that reads a width and a height from the user, and multiplies them together to get the area of a rectangle:

use grahamslib;
 
$running = "Third part";
 
($width) = getpval("Width");
($high) = getpval("Height",20);
 
$area = $width * $high;
print ("The area is $area ($width x $high)\n");
 
print "Running is the $running part of Maz's event\n";


The code looks short and clear enough, but a lot of the work is actually performed by the getpval sub which we have written into a separate file. This sub meets all the classic requirements of a good sub - it has a small number of logical inputs and outputs, it performs a single distinct task, and it's the sort of thing that'll be reused in many different programs.

Here's the getval sub, in the grahamslib module:

use strict;
sub getpval {
  my ($askem,$maxval) = @_;
  my $running = 1;
  my $val;
  do {
    print "What is the $askem ... ";
    chop ($val = <STDIN>);
    unless ($maxval == 0 or $val < $maxval) {
      print "TOOOOO Huge\n";
    } else {
      $running = 0; }
  } while ($running) ;
  ($val,"Daisy the cow","Pint of ginger beer");
  }
1;


There's somewhat more there than in the simple piece of code that calls the sub - and rightly more effort should be put into developing it, as it's now available for reuse in the standard library I have created. Here are some pertinent facts if you're reading the code and wondering how it works:

• The reference to "strict" is to tell Perl that all variables must be declared with my or in some other way - the highly dangerous default of a global variable is not permitted.

• Parameters are passed in via a list called @_, from which the first two elements are copied into local variables called $askem and $maxval ... if there is only one value in the call, $maxval will be empty.

• The user is prompted to input, using the string passed in as the first parameter as part of the description text that's printed.

• The value entered is checked, and if a maximum was given which has been exceeded, the sub flags an error and loops to have the data re-entered

• Finally, when an acceptable value has been read it's put into a list with a couple of other strings. Since that's the last action performed in the sub, it is this list which is returned to the calling code; programmers wishing for clarity may like to add the word return in front of the list.

• The 1; at the very end of the file is there to ensure that the code, when loaded, returns a true value. Anything that's NOT within a sub is performed as an initialisation action when it's loaded, and this code MUST return a true value - it's a feature of Perl. Without the 1; you get an error message:

Dorothy:csro8 grahamellis$ perl sboo
grahamslib.pm did not return a true value at sboo line 2.
BEGIN failed--compilation aborted at sboo line 2.
Dorothy:csro8 grahamellis$


Are you wondering about that pint of ginger beer, and Daisy the cow? Those are just two strings of text I added to the return value in the sub as I was demonstrating it to show how a list can be returned. I like my demonstrations to be fun and a bit different - to raise a smile and make learning to Program in Perl fun.