« October 2008 | Main | December 2008 »

November 30, 2008

Alastair Darling helps make paperwork and confusion

Quite frankly, I'm not convinced that a drop in VAT from 17.5% to 15% is going to bring us much - if any - new business. A hotel room at our top rate of £95.00 should drop to £92.98 ... an awkward sum, as comes from nearly every VAT inclusive price we would change.

It will shake out in the wash for most of our customers who work for VAT registered companies anyway ... so would end up paying the same base price. I understand that VAT is typically reclaimed some six times in this way for every seven times it's paid - so its efficiency as a tax sucks at the best of times. But we do have a small proportion of our customers who are not VAT registered - either being private individuals who stay at the weekend, or overseas visitors; alas, I don't see many "buying decisions" being based on a 2 pound and odd pence saving.

But it's not just a non-event. Systems need to be changed to reflect the new VAT rate. Our own course booking page and hotel room booking page changed very easily as they were coded with maintainance in mind, but never the less Lisa is left with an accounting nightmare of courses, rooms and events that were booked before the announced changed that need to be re-confirmed at slightly lower prices, and she is not looking forward to fighting the Sage software that she uses for our accounts to reflect the 17.5% rate to 30th November and the 15% rate to 31st December in the current tax quarter.

I really dislike the idea of our pricing going from a set of nice, round numbers to some really nasty odd values - and I suspect that other suppliers feel the same. A TV that costs £399.99 at those high street stores that always charge "a penny shy" should come down to £391.48 ... but I would be surprised if it does; some headline products may come down further to £389.99 but I would fully expect most to quietly remain at £399.99 - in effect, an improvement in margin for the retailer, at a loss to The Chancellor for non-VAT registered purchasers and a price RISE for other businesses. And, alas, businesses need to make a profit, and pass price rises on.

So we're left in something of a quandary. Do we simply cut our VAT inclusive prices by £2.13 in every £100.00 ? And what then if our suppliers don't follow the same scheme ... we would be out of pocket. Do we leave our prices unaltered, and quietly thank Mr D for helping our business (but what would our customers think, and would that be morally correct?) Or do we come up with some other scheme, taking a whole fresh look at pricing?

• Any events and hotel rooms were already booked at a fixed, VAT inclusive price will indeed be invoiced at a 2.13% lower rate - passing on the VAT saving on the contract that's already in place.

• Training courses which are quoted VAT exclusive anyway will simply have the lower VAT rate applied when invoiced, resulting in a 2.13% lower bill. This will also apply to any other short term bookings that we receive.

• Hotel room prices are being slightly reduced - but NOT across the board. It is our intent that the new VAT inclusive prices should be easy-to-quote numbers, that we should pass on the VAT saving, and that the prices should also be fair in relation to each other. So that top rate of £95.00 for a double I talked about at the beginning is down to £90.00 - which is a saving of more than just the VAT reduction. We're taking the opportunity to even out the £70.50 delegate rate down to £70.00 - a slight saving. And the single rate remains at £80.00. Nice and easy pricing - £90, £80 and £70.

• In the near future, we'll have new pricing for the hire of training and meeting rooms at Well House Manor and those prices will reflect the actions of our suppliers; this is a particularly cost sensitive part of our business, and also one where we have the most VATable supplies being purchased in to pass on to the attendees - so a promise at this point to cut our price long term in line with the VAT change is simply one I cannot make.

Oh my goodness, Mr Darling ... did you really think this through?

Posted by gje at 06:46 AM | Comments (0)

More about Graham Ellis of Well House Consultants

November 29, 2008

Book now for 2009

We review our prices every 1st January, and at this time of year often say something like "Book now to be assured of getting your 2009 course at the 2008 price". But this year, I can predict rather earlier than usual, that we'll be holding the majority of our prices once again. And with course prices quoted exclusive of VAT, there's an automatic and immediate reduction from Monday 1st December - for every £100.00 spent by non VAT registered customers up until now, we'll only be charging you £97.87 - a saving of £2.13.

So why should you book for 2009, even before Christmas?

• courses are already booking - dates getting snapped up, with some already not available. Remember that bookings are on a first come - first served basis.

• we'll guarantee that - if you *do* hit one of our price adjustments - you'll pay the lower of the December 2008 and 2009 rates.

• and of course YOU should be planning ahead - ready to hit the road running in 2009 rather than getting back in the New Year and saying "what now" ... 2009 is going to be an interesting year!

And, yes, I have to admit it ... by booking ahead, you're helping us plan ahead too and we'll be very grateful - and the better we can look ahead, the better we can serve our customers!

First Courses for 2009

PHP

PHP Techniques - 2 days starting 8th January 2009
PHP Programming - 4 days starting 2nd February 2009
Other PHP courses

Web Server Deployment and Linux

Apache httpd and Tomcat Deployment - 2 days starting 29th January 2009
Linux Basics - 1 day - 23rd February 2009
Other Linux and Web Server courses


Perl

Perl Programming - 5 days starting 2nd March 2009
Other Perl courses

Python

PHP Programming - 3 days starting 26th January 2009

C and C++

C Programming - 2 days starting 19th January 2009
C++ Programming - 2 days starting 21st January 2009
Other C and C++ courses

Lua

Lua Programming - 3 days starting 23rd March 2009

Ruby

Ruby Programming - 2 days starting 26th March 2009

Tcl

Tcl Basics - 3 days starting 23rd March 2009
Other Tcl courses

MySQL

The MySQL database - 2 days starting 26th March 2009

See here for a full course index, sorted by date, from today for the next 6 months ...

The weeks of 16th February and 9th and 16th March are currently open for private courses (as are a number of other odd days), but please check back with us as this is just a "snapshot".

Posted by gje at 08:07 AM | Comments (0)

November 28, 2008

Remember Me - PHP

Here's a paradox for you as a web site designer, when putting together a web site which requires a login.

Most of your users are regulars, who really don't want the hassle of logging in every time they visit ... but at the same time, you can't allow blanket, long term logins as your site is often accessed by legitimate users from public access / shared computers on which permanent cookies should not be left.

The solution - and I'm sure most of you will have see it on any number of sites like forums - is a "remember me" box. Simple and easy - your users will be defaulted to a short session of, say, 30 minutes ... but if they check the box, their logins will last for a much longer period.

We use our own web site for much of our internal communications and for our various status pages. With Headquarters, booking and admin office on the outskirts of Melksham, and a Training Centre and Hotel near to the town centre ... and with me often giving On Site Courses many miles from home, this is a key form of communication. From the Admin systems that Lisa runs, from the laptops which are assigned to the rest of us personally, we need to be able to be in touch with a minimum of keystrokes. And we need to be able to check on the status from the reception computer, from trainee laptops, and from the public access system too. It goes even further than that - I need to be able to borrow a customer's keyboard on site (behind the customer's firewall where I cannot have access from my own system!) and still check and update the status.

Until now, we've been very careful to remember to log out from a shared computer ... but there are times that all of us have got called away from such a system - perhaps to carry on with Customer Service which is the reason we logged in, in the first place. So this morning, I've added a "remember me" box into our main login script.

It's in PHP, and the extra code is very straightforward.

The extra check box:

<input name=mine type=checkbox> Remember me!

The code that works out the login period:

$days = 0.02;
if ($_REQUEST[mine] != "") $days = 14;
pwlogin($a,$days);

and the login function that sets the cookie:

function pwlogin($arriving,$days=7) {
global $pwname;
setcookie("whcttt","$arriving:$pwname", time()+3600*24*$days,"/",".wellho.net");
$_COOKIE[whcttt] = "$arriving:$pwname";

The only thing that may be something of a surprise package in that code is the last line - setting the $_COOKIE superglobal to the same value that is being sent out to the browser. That's done to allow the user to be logged in on the current ("congratulations, you have logged in") page as well as on subsequent pages.

Posted by gje at 08:54 AM | Comments (0)


Useful link: PHP training

November 27, 2008

Java - Generics

If you're writing a Java program and you want to hold a whole series of objects of a similar type in a single variable, you can use and array ... except that you need to know HOW MANY of them there will be before you create the array.

Using the java.util package, there are numerous more flexible alternatives - you can used a Vector or ArrayList if you want an ordered collection, or a HashTable or HashMap if you want a keyed (unordered) collection from which you select elements by 'name'.

You can declare a HashMap (as an example) as follows:
HashMap results = new HashMap();

BUT when you compile your code, you'll get:
[trainee@easterton b2]$ javac Req.java
Note: Req.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
[trainee@easterton b2]$

And when you press it a bit, you get:
[trainee@easterton b2]$ javac -Xlint Req.java
Req.java:19: warning: [unchecked] unchecked call to
put(K,V) as a member of the raw type java.util.HashMap
results.put(person, firstSkill);
^
1 warning
[trainee@easterton b2]$

What's all this about?

Vectors, ArrayLists, HashMaps, and HashTables can store any object types, and the Java compiler is worried about typing - that you'll put something into one that you don't mean to, and get a run time error when you pull it out. But from Java 1.5 you can use a generic which lets you tell the java compiler what types it should accept into the collection - in the case of ArrayList and friends that will be a single type definition, and in the case of a HashMap and friends it will be two types. Here's an example:

HashMap<String,String> results = new HashMap<String,String>();

Result? A clean compile:
[trainee@easterton b2]$ javac Req.java
[trainee@easterton b2]$

And also a re-assurance that what comes back out of your collection at runtime is what you expected!

Posted by gje at 04:39 PM | Comments (0)


Useful link: Java training

November 26, 2008

javax.servlet cannot be resolved - how to solve

Two common problems in compiling Servlets for use within a Tomcat container ...


PROBLEM: My Java Compile of a Servlet says "javax.servlet cannot be resolved"

For example:

[trainee@easterton sources]$ javac Smallest.java
----------
1. ERROR in Smallest.java
 (at line 2)
   import javax.servlet.*;
          ^^^^^^^^^^^^^
The import javax.servlet cannot be resolved
----------
2. ERROR in Smallest.java
 (at line 3)
   import javax.servlet.http.*;
          ^^^^^^^^^^^^^
The import javax.servlet cannot be resolved
----------
3. ERROR in Smallest.java
 (at line 5)
   public class Smallest extends HttpServlet {
                                 ^^^^^^^^^^^
HttpServlet cannot be resolved to a type
----------
4. ERROR in Smallest.java
 (at line 9)
   public void doGet(HttpServletRequest request,
                     ^^^^^^^^^^^^^^^^^^
HttpServletRequest cannot be resolved to a type
----------
5. ERROR in Smallest.java
 (at line 10)
   HttpServletResponse response)
   ^^^^^^^^^^^^^^^^^^^
HttpServletResponse cannot be resolved to a type
----------
6. ERROR in Smallest.java
 (at line 11)
   throws IOException, ServletException
                       ^^^^^^^^^^^^^^^^
ServletException cannot be resolved to a type
----------
6 problems (6 errors)[trainee@easterton sources]$


SOLUTION: Add the Servlet API to your CLASSPATH.

[trainee@easterton sources]$ export CLASSPATH=/usr/local/tomcat/common/lib/servlet-api.jar 
[trainee@easterton sources]$ javac Smallest.java
[trainee@easterton sources]$

EXPLANATION:

Even if you're just compiling a Servlet to produce a class file, on a machine on which you won't actually be running it, the Java compiler insists on having the necessary classes available to check you code / to know what it is extending.

The Servelet API jar file is available from within a standard Tomcat download, and also from within a Java Enterprise download, but it is not downloaded with the standard edition!


PROBLEM: I get an error message about "does not declare serialVersionUID"

[trainee@easterton sources]$ javac Smallest.java----------
1. WARNING in Smallest.java
 (at line 5)
   public class Smallest extends HttpServlet {
                ^^^^^^^^
The serializable class Smallest does not declare a static final serialVersionUID field of type long
----------
[trainee@easterton sources]$

SOLUTION: Check that you're using the correct Java compiler!

1 problem (1 warning)[trainee@easterton sources]$ which java
/usr/bin/java
[trainee@easterton sources]$ export PATH=/usr/local/java/bin:$PATH
[trainee@easterton sources]$ javac Smallest.java
[trainee@easterton sources]$

EXPLANATION: There are various Java Compilers available, and the one that's shipped with Linux releases is highly unlikely bo be Sun's one which you'll want to use with Servlets / Tomcat's classes.

If you have Tomcat downloaded and installed already, chances are that you do have the right compiler already on your system - if not, download it from Sun - but that your PATH to executable files is currently pointing at the one shipped with the operating system.


Learn all about these on our Deploying Apache httpd and Tomcat course!

Posted by gje at 08:03 AM | Comments (0)


Useful link: Java training

Java CLASSPATH explained

When you run a Java program (be it though the java virtual machine or as a servlet within a web or application container such as Tomcat), it's only the main code (class) that's initially loaded. Any other code (classes) are loaded in dynamically as needed.

Where are these classes loaded from?

They're loaded from EITHER directory structures OR jar files, and the locations of these are in part defaulted (for the standard stuff) and in part defined by the CLASSPATH - an environment variable in which you list the root of the tree in which the JVM (Java Virtual Machine) should start looking. Let's see an example:
   export CLASSPATH=/home/demo/packages:/usr/local/tomcat/shared/lib/wellhouse.jar:.
will cause the JVM to start looking in the packages subdirectory of the demo user's home directory, in a shared directory in your Tomcat installation, and in your current directory.

But that's only where it will start looking. If you're calling in a class called (say) net.wellho.tomcourse.Animal, then the extra package names will be added on to the base path and the actual files looked for on your disc will be:
   /home/demo/packages/net/wellho/tomcourse/Animal.class (an absolute path)
   /usr/local/tomcat/shared/lib/wellhouse.jar ... within in, the file ./net/wellho/tomcourse/Animal.class
   /net/wellho/tomcourse/Animal.class (i.e. below the current directory)

There are even more places that will be searched if you add some import statements to your Java class. Let's say you're loading from a class that includes:
    import net.wellho.general.*;
    import net.wellho.tomcourse.*;
    import org.apache.tomcat.*;

then you'll end up looking in no less that 12 places if you simply call up a class called Animal using the earlier CLASSPATH example:
   /home/demo/packages/Animal.class (an absolute path)
   /home/demo/packages/net/wellho/general/Animal.class (an absolute path)
   /home/demo/packages/net/wellho/tomcourse/Animal.class (an absolute path)
   /home/demo/packages/org/apache/tomcat/Animal.class (an absolute path)
   In /usr/local/tomcat/shared/lib/wellhouse.jar for Animal.class
   In /usr/local/tomcat/shared/lib/wellhouse.jar for net/wellho/general/Animal.class
   In /usr/local/tomcat/shared/lib/wellhouse.jar for net/wellho/tomcourse/Animal.class
   In /usr/local/tomcat/shared/lib/wellhouse.jar for org/apache/tomcat/Animal.class
   ./Animal.class (below the current directory)
   ./net/wellho/general/Animal.class (below the current directory)
   ./net/wellho/tomcourse/Animal.class (below the current directory)
   ./org/apache/tomcat/Animal.class (below the current directory)

Remember too that the Java compiler (known as javac) checks your code - so that it needs access to all necessary classes on the machine you're developing / compiling on to ensure that you're only calling classes - and methods within them - that actually exist. So if you're writing a Servlet, for example, you'll need to have the Servlet API on your CLASSPATH on the development machine and in the development environment, as well as on the test and production servers.

Posted by gje at 07:06 AM | Comments (0)


Useful link: Java training

November 25, 2008

Melksham Hotel Rates

Melksham Hotel Rates - Well House Manor - VAT changes

We're passing on the reduction in VAT rates to our customer; with immediate effect, room rates at Well House Manor are reduced to:

90 pounds per night - hotel guests, double room, double occupancy
80 pounds per night - hotel guest, double room, single occupancy
70 pounds per room per night - course delegate and contract rate

Well House Manor is set in 3/4 of an acre of grounds, just 5 minutes walk from Melksham Town Centre, and is designed with the business traveller in mind. All rooms are large and en suite, with large, flat screen TVs with over 50 channels, a spacious work desk, mini fridge, laptop safe, etc. Wired and wireless internet access is available throughout the hotel. Room prices include a superior continental breakfast buffet, served from 7 a.m. for the early business riser.

Well House Manor will be open over Christmas and the New Year, when we'll be welcoming friends and relatives visiting their loved ones in Melksham for the festive season. Please book ahead of time though, as accommodation is limited.

Link - Well House Manor home page

Our delegate and contract rate is available to delegates on our training courses, to guests booked with other functions at Well House Manor,and to regular client companies who book a minimum number of nights per month.

Posted by gje at 07:18 AM | Comments (0)

Long, Longer, Longest in Java

If you want to find out how long a Film3 is, in the class that I use on our private Java Programming courses, you can call the getminutes method. That's standard OO stuff. But what if you want to find out which is the longer of two Film3s or the longest of a whole array of them?

Don't re-write code!!!. So your longer method should call getminutes, and your longest method should call either longer or getminutes directly. Here's an example:

public int getminutes() {
   return minutes;
   }
public Film3 longer(Film3 that) {
   int m1 = this.getminutes();
   int m2 = that.getminutes();
   if (m1 < m2) return that;
   return this;
   }
public static Film3 longest(Film3 [] ofthese) {
   Film3 sofar = ofthese[0];
   for (int owabout=1; owabout<ofthese.length; owabout++) {
   sofar = sofar.longer(ofthese[owabout]);
   }
   return sofar;
   }

longer is a method that runs on one object, with another passed in as a parameter:
  current = Library[1].longer(Library[2]);

By contrast, longest is a class or static method that runs on a whole array of objects:
  current = Film3.longest(Library);


You might wonder if longest could simply have run on the class as a whole and returned the largest defined Film3, but that would not be a good solution as you're likely to want to find (say) the longest horror film or the longest one for children, which will all be defined at the same time.

Links - Sample Program and the class that goes with it

Posted by gje at 01:00 AM | Comments (0)


Useful link: Java training

November 24, 2008

A Gold Star for First Great Western Customer Service

Regular readers will know that I've been running something of a campaign for the return of an appropriate train service in Melksham, and that First Great Western (who took over a service of 5 each way per day on 1st April 2006 and reduced it to just 2 dreadfully timed trains the following December) are not exactly a company who's every action I could admire. However, the duty staff get a big bouquet for their actions last night in helping my customers get to Melksham when the London to Penzance express got delayed, and their connection into the second (and final) train of the day from Westbury - the 19:35 - missed.

An announcement on the express that anyone who wanted to catch the connection to Melksham and Chippenham should contact the Train Manager, and then when they arrived in Westbury they were expected and a large taxi (there were 7 people going on) had been arranged.

Read more about it here and about delayed connections here

And ... a Gold Star (or whatever one gives!) to Ben at First Great Western Customer support, who I phoned when I saw on the online departure board that there was going to be a problem, to ask when and where my customers would be arriving in the circumstances. Further Gold Stars to FGW Control in Swindon for co-ordinating, the train manager on the express for finding and keeping the customers informed, the station staff at Westbury for doing a grand job of organising the taxi, and tot he taxi driver for dropping the folks off at our door rather than insisting he drove right past to the station.

In fact ... I need to go out and buy a new supply of * * * * * Gold Stars!

Posted by gje at 06:44 AM | Comments (0)

November 23, 2008

Ruby, Perl, Linux, MySQL - some training notes

We have just come to the end of a solid 12 days of training ... and we are just getting ready for the next week, with delegates arriving this evening. There's a lot going on behind the scenes, even over this weekend, with the hotel to be prepared as well as the training course. (Picture - our clean bedding racks at Well House Manor)

So I'm taking an all too brief opportunity to post up some pictures from the last hectic fortnight, before the next hectic fortnight begins in a few hours time. You'll find, below, some technical notes and scripts mixed in with some rather less technical stuff.


If you're writing / installing a web based application that used Perl and CGI to access a MySQL database, don't just plug all the components in and hope they work first time ... they might, but if they don't you'll have a woozie of a job sorting out which is functioning and which not.

Test your database first - that's (1) on the diagram. Then add in a Perl application from the command line - using the DBD and DBI modules, and make sure that works. That's (2) on the diagram. The add in your web server, and CGI, and run it from a browser - step (3). Three easy steps rather than one very difficult one.

From our MySQL course, with reference made to Perl on the Web


In Ruby, you have no fewer that four different ways of changing the flow control with jumps. They are break, next, redo and retry, and the diagram shows the effect of each of them if used within a condition inside a loop.

Computer Science purists will tell you that you should never use a goto statement as it rapidly turns your logic into spaghetti - and indeed Ruby does not have such a statement. However, it has been argued that these four jumps are tame forms of the 'goto', and that they should be used with caution.

From our Ruby Programming course


Melksham Chamber of Commerce met at Well House Manor during the recent run of courses (we're nothing if not versatile!) for their AGM and an EGM.

With the current re-organisation of local government in Wiltshire, which sees the replacement of five bodies by just one, with a more than halving of the number of elected representatives, this is a time for local traders who do business with these bodies to be aware of what's happening, and to position themselves to do well in 2009 and beyond. It was frightening (at another recent meeting) for those of us who live in Melksham to hear the chiefs of the new council talking, as if to a script, of the three largest towns in the county when they spoke of future development, ignoring the fourth (Melksham) and many others places ... the Chamber of Commerce could be so important next year.


Q: If you have a database table with 32 patients in it, and another table in the same database with 50 clinical operations in it, how do you link the tables together?

A: With a join. But it's not necessarily as simple as that. If you have some patients who have never had any operations, will they appear in your resulting data set? That depends on whether or not you specified JOIN or LEFT JOIN. And what about operations that have been erroneously entered into your database as they relate to patients who aren't a part of your sample group ...

In this example, we show how you can have five different sets of results:
• All the records that match
• All the records that match PLUS and extra record for each patient who hasn't had any operations
• All the records that match PLUS and extra record for each operation which isn't assigned to any patient
• Just the records for each patient who hasn't had any operations
• Just the records for each operation which isn't assigned to any patient.

From our MySQL course, or if you want more detail see our join v left join page


The /etc directory of the Unix and Linux operating systems includes many configuration files ... the rather poor picture to the left showing the more important ones (or the ones which were more important to the delegates on my recent LAMP deployment course on which we set ul Linux, and a Web server with MySQL and PHP.

The directory /etc/sysconfig/network-scripts. In this directory you'll find the configuration files for the network interfaces, where the IP address, netmask, gateway address, and so on are set.

The directory /etc/init.d. Holds all the scripts you could (possibly) want to start up and shut down daemon services. Each script responds to the parameters "start" and "stop" to (you guessed it!) start and stop services. Whether a script is actually run or not depends on directorys such as rc5.d

The directory /etc/rc5.d. A directory full of Symbolic links to /etc/init.d. You place a link to a file in /etc/init.d, and you name that link starting with an S, if you want the particular daemon to be started as the computer restarts into "run state 5". You place a link starting with K if you want the daemon to be properly closed down on shutdown. The naming of the links is important as they are run is ACSIIbetic order. If you are running a server which is NOT running the X Windows System, you'll be concerend with /etc/rc3.d and not /etc/rc5.d

/etc/inittab. Linux / Unix startup script. The only thing you many commonly change is the initial run state - i.e. to control whether or not the X Windows GUI is activated on bootup.

/etc/fstab. The mounting of the various disc drives, slices, and pseudo devices onto the Linux / Unix file tree.

/etc/nsswitch.conf. This file controls where the operating system looks for login accounts, host computer names, and much more - whether to look in local files, in network services, or in both ... and in what order.

/etc/resolv.conf. The IP addresses of the machines that your system is to contact to help it resolve unknown host computer names back to IP addresses. "The next step in the DNS chain".

/etc/hosts. Maps locally known host names to IP addresses and vice versa.

/etc/passwd. Local user account definitions - user name, user number, home directory, program to run when the user logs in. In fact everything EXCEPT the password, in spite of the name of the file.

/etc/shadow. A file of user names and their encoded passwords. This was separated out from /etc/passwd a good few years ago, so that the encoded password information could be held in a file with fewer access rights than /etc/passwd. If you're editing this file with vi, remember to save it with :w! rather than :w to override its read-only nature.

/etc/group. A file that defines names for each of the groups, and also defines any uses who are in a group in addition to their default group which is specified in /etc/passwd.

/etc/bashrc. A file of bash shell commands which is run by each user when they log in - allows for the centralised setting of default file permission via umask, for example.

The directory /etc/skel. A skeleton directory that's duplicated to each newly created user if the appropriate option is selected when you run the useradd command.

From our Introduction to Linux Administration course.


It's always a fine line during a training course as to whether we should go out for lunch - taking a little longer, but giving delegates a good break and a chance to stretch their legs, or eat in - allowing us to make the maximum use of course time.

Here are Thursday's Pizzas, prepared and cooked by Sharon, so that we could make the very best of the time we had on our Deploying Apache httpd and Tomcat course. In fact, even though the lunch break was brief we ran on until 6 p.m. in the afternoon, as a disparate group of delegates had a lot of wonderful questions to ask, and none of them wanted to run too late on Friday!


There are a number of different shell programs (programs that look after the user's keyboard commands, and the operating system's responses to the user) available on Unix / Linux. Ask me sometime to tell you about the Bourne Shell (sh), the C Shell (csh) and the Korn Shell (ksh) - the latter two remaining popular in some quarters. Under Linux, thoughh, the most commonly used shell is now the Bourne Again Shell or bash.

This slide shows you some of those extra facilities of bash which are different to (or absent from) some of the other shells.

• If you press [tab] while entering the name of an existing file, bash will attempt to auto-complete it for you. Not only time saving, but also helps avoid too many mistakes - if a [tab] doesn't respond, it can be a quick way of finding a spelling mistake you've already made.

• The set -x causes subsequent shell commands to be echoed back to you, with details of how the shell / operating system has interpreted them. A great debug and learning tool which can be switched back off with set +x

• The history mechanism in bash is similar to that of the cshell. (and different to that in ksh!). So you can use:
!$ Last parameter, previous line
!! Rerun the last command
!gr Rerun the last command starting with gr
!442 Rerun command number 442

From our Linux Basics course.


Directory navigation on a Unix / Linux box is controlled by how you start the file or directory name that you're typing in:

If you start with a /, you're talking about an absolute path from the top of the file system tree.

If you start with a ./, you're talking about something in the current directory.

If you start with ../, you're going up from the current directory.

If you start with ~/, you're going relative to your home directory.

If you start with ~fred/, you're going relative to fred's home directory.

and is you start with another character, you'll be looking within the current directory that you're in.


The vi editor is the only editor that you can be sure of finding on any Unix or Linux system - and it's darned good. However - it is easy to use once you know it, rather than being easy to learn. That's why some people will tell you that vi stands for "virtually inoperable" rather that "visual interactive".

The "trick" to learning vi is to understand that each key on the keyboard is a command - usually a single letter command - when you enter vi, with upper case, lower case, and control keys each meaning something different. Once you have entered an insert mode (i or a or o or cc or cw .... or others), you are in insert mode and anything you type is added in to your text. You return to command more by pressing the [esc] key. A final mode - "ex mode" is entered by pressing the colon key, and in this mode you type in a command followed by a [cr].

The diagram on the left shows a minimum of vi commands - we have an article that takes you through those commands here.


The week finished with a trip to the station to drop off a delegate for the train to take him home, from Melksham to Luton via London. And, this evening, the next course will start with me meeting the train and greeting our next group of delegates. I'm looking forward to it.

Posted by gje at 12:12 PM | Comments (0)


Useful links: Linux training, Perl training

daemons - what is running on my Linux server?

Processes which (re)start when you start your computer and run until you halt it are known as services in the Microsoft world and daemons in the Linux and Unix world. As well as providing support for the operating system and user, the service / daemon mechanism is used on server computers to provide the processes that listen out for requests, and handle them.

On the left of this article, you'll see a list of the more significant daemnon processes running on our server, as discuseed / taken from our Linux Web Server course.

memcached. A memory caching daemon that lets us save the results of complex database requests to improve server throughput. Of all the daemons that I have listed on this page, this is the one you'll see the least often.

tomcat. The Apache Tomcat web server, which is a container for Java based applications written to the Servlet or JSP standards. You'll find Tomcat used for high traffic web applications, where re-loading the page on the server every time it is called up would be inefficient.

mysqld. This provides the service that lets other applications read and write data to / from the MySQL relational database.

httpd. The Apached httpd web server - this is the daemon that turns your computer into a web server ... listening for connections from browsers, and sending out the appropriate pages in response. You'll normally find that you are running multiple httpd processes on your server, as the daemon adjusts itself to have sufficient copies on hand to handle incoming traffic. On systems with both httpd and Tomcat, it's httpd than handles the incoming requests, which is passes on (proxies) to Tomcat as necessary if a Java program is to be run.

sshd. The Secure Shell daemon, which allows the system administrator (and others if authorised) to log in to the server remotely to update settings, the web site, etc, and to run other programs on the server.

crond. Jobs which you schedule via the at or batch or crontab commands are started and controlled by this daemon. A good example of its use it to take a copy of your server log files in the middle of the night, and to start a new log file.

lpd. If you have a printer attached to (or controlled from) your computer, lpd takes print requests and handles them for you, without you having to wait for the print request you've made to actually complete before you get on with your next job. It also allows several people to share a printer without any risk of their data getting mixed up.

ftpd. This daemon provides facilities for file uploads and downloads for authorised users using the File Transfer Protocol. Typically, FTP is used by web site maintainers to upload new pages, applications, images, etc, and by administrators to download backups and copies of log files.

sendmail. If your server is also an email server, sendmail is one of the daemons that you may use to handle the management, routing and transfers of email.

Posted by gje at 09:07 AM | Comments (0)


Useful link: Linux training

sstrwxrwxrwx - Unix and Linux file permissions

Have you ever wondered about those letters that turn up on the left of a long listing (ls -l) report? Here's an example:

drwxrwxrwt   8 root    wheel    272 17 Nov  2007 Shared
drwxr-xr-x  14 chris   ellis    476 29 Sep  2007 chrise
drwxr-xr-x 270 graham  ellis   9180 23 Nov 07:25 grahame
drwxr-xr-x  34 lisa    ellis   1156 27 Sep 06:44 lisae
drwxr-xr-x  29 trainee trainee  986  5 Sep 03:55 trainee
-rw-rw-r--   1 graham  ellis    294 23 Nov 07:41 uu
-rw-r-----   1 graham  ellis    922 21 Nov 08:45 wb
-rw-------   1 graham  ellis   5143 23 Nov 07:25 xx

They're split into two sections.

The first character is the type of symbol (ls literally means "list symbols") with d for directory, - for a plain file, l for a symbolic link - call it a short cut if you're from a Windows background.

The rest is displayed as 3 sets of three. The first group of three tells you what permissions the user (owner of a file or directory) has over it - that's r for readable, w for writable and x for executable. The second group of three is the permissions thank anyone else in the group has, and the final set of three is for otheirs.

The chmod command lets you change the settings - for example
  chmod g+w,o=r wb
would change
  -rw-r----x 1 graham ellis 922 21 Nov 08:45 wb
into
  -rw-rw-r-- 1 graham ellis 922 21 Nov 08:45 wb

If you wonder why a directory is often marked with an "x" ... I can tell you. It's because "x" means 'accessible' and not 'executable' for a directory - so you need to have the x set for things like cd and ls -l to work properly.

And did you notice the "t" in my top sample. There really should be 12 (and not 9) permission letters ... it should read sstrwxrwxrwx. But those extra letters, where necessary, are displayed "on top of" the "x":

What do they mean?

The two "s" letters stand for "set user id" and "set group id". Normally, when you run a program you're running it with your own permissions, but if the "s" bit is set you run it with the permissions of the owner of the file. If you want an example of a practical use of this, take the password changing program /bin/passwd; regular users cannot be allowed to directly read and write the file of passwords on their computer, but they can write back to it via the direct control of the passwd program. It is dangerous to set the s bit on a program of your own unless you are an expert, know what you are doing, and have considered the security implications!

The letter "t" usually turns up on directories rather than plain files these days, and indicates that the directory is to be an "append" directory. With a regular directory which has public write permissions (such as the one called Shared in my example at the top), anyone can create and delete ANY files there. With the "append" bit set, each file within the directory can ONLY be deleted by the owner of the file, the owner of the directory, and root. The effect of the "t" bit, then, is to provide a temporary / scratch area that anyone can use, without the different users of the area being able to interfere with each other.

Posted by gje at 08:16 AM | Comments (0)


Useful link: Linux training

XML, HTML, XHTML and more

HTML is a language ... but XML is a Metalanguage. In other words, you can write something in HTML and have it (quite) well defined, whereas anything you write in XML has to have another layer of definition there to tell you what's valid and what isn't. XML is a set of over-arching rules in which you can define your own, XML compliant, language ... or use one that someone else has already defined for you, such as RSS, SOAP, REST, or XSLT or XHTML. Here's a diagram:

It's been said - and it's usually the case - that if you define your data using HTML, then you're defining how it looks, whereas with XML you're defining what it is. For example:

HTML - says how it should appear:

<h1>Melksham Town Center</h1>
<ol><li>Woolworths, Boots, Peacocks and Iceland
<li>All the major banks
<li>Tourist Information Center and Post Office
<li>Bus to Bath, Devizes, Chippenham and Trowbridge
</ol>

XML - says what it is:

<place>Melksham Town Center
<facility><chains><item>Woolworths</item>
   <item>Boots</item> <item>Peacocks</item>
   <item>Iceland</chains>
<banks><item>All the major banks</item></banks>
<general><item>Tourist Information Center</item>
   <item>Post Office</item></general>
<bus><item>Bath</item> <item>Devizes</item>
   <item>Chippenham</item> <item>Trowbridge</bus>
</facility></place>

From that, you'll see that you can see how the HTML will be displayed, but you don't know how the XML will be used of displayed. There needs to be a tailored intermediate piece of software specifying that, and doing the work. You may come across:

SAX - The Simple API (Application Programmer Interface) for XML (Extensible Markup Language)

Using SAX, a stream of XML data is passed through a process (scanned by a program) and the interesting bits that the program needs are collected as it does. I've describe this as pouring a lot of water through a sieve, and catching the bits that you want in the sieve. SAX is ideal for getting a few specific elements out of a very large flow of data, but is exceedingly poor for reading XML to edit and re-save it.

DOM - The Document Object Model

In DOM, Data is parsed into a structure in memory. An XML document is a series of tags ... so each of those becomes an array or list (depending on the programming language that you're using), and within each of those you have other tags which in turn become further arrays or lists within the first. Attributes - not touched on in this article - become hashes, dictionaries or associative arrays, and the text data is stored as strings in the arrays. So this translates from file to something that can be held in memory and, with carefully written recursive code, manipulated very flexibly indeed. DOM is good for smaller data sets, and it's a great tool if you want to edit and save changes to your original XML. It's not going to work for you if you have an enormous XML file.

XSLT - XML Style Sheet Language Transforms

XSLT is a language which allows you to specify how your XML is to be transformed, SAX style, as you parse it. You can write formatting information, tags, loops and all the other things you're used to in XSLT ... and the result of an XSLT transform is likely to be XHTML. Let's say you have 60 staff, with an XML file holding records for each of them. And you want to display the data in 3 different ways. Then you'll write 3 XSLT files to define the mappings, and the result will be that you can get any of your 60 x 3 (=180) possible displays. XSLT happens to be itself defined to the XML standard ...

Cocoon

Apache Cocoon is a system that allows you to take XML and transform it into different formats for different purposes - taking my "staff record" example again, I could set up Cocoon to give me postscript files for printing, XHTML for display, selective XML for public release via a news feed, pdf for producing a flyer about the employee, and so on.

And how does XHTML fit into this?

XHTML is HTML with the additional rules of XML enforced - so that although you're laying out how things are to be displayed rather than what they are, you're also specifying that in a consistent form that's easy to edit with HTML editors and will cause less headaches as you view your page on different browsers - assuming you stick with standard tags!

Our example in XHTML:

<h1>Melksham Town Center</h1>
<ol><li>Woolworths, Boots, Peacocks and Iceland</li>
<li>All the major banks</li>
<li>Tourist Information Center and Post Office</li>
<li>Bus to Bath, Devizes, Chippenham and Trowbridge</li>
</ol>

Posted by gje at 07:19 AM | Comments (0)

November 22, 2008

Table Topics

Here's a link for the delegates who were with us at lunchtime yesterday ... it's to Table Topics. L**** picked up the little box that we have left lying around near the dining table in our eating room, and started reading out, aloud, some of the cards.

Those who wanted ... answered. Those who didn't wish to respond ... listened. And a quiet table turned into a fascinating discussion. Were the subjects too deep? No - and they're not too deep for groups such as we have on our courses; rather, they extend the keen learning experience that everyone's having on the course (Apache httpd and Apache Tomcat in this case) to wider areas - to appreciate the background and learn from the life experience and views of people who originate from disparate parts of the globe, and who came on the course from disparate parts of the UK and elsewhere in Europe.

It's our view that you should learn on a training course - and you enjoy your time here too. And that the learning and enjoyment should not be restricted to the main course topics; after you've exhausted your capacity to learn about Apache Tomcat, why not enjoy the company of, and learning about, your fellow delegates, and the staff and tutor running the course too? I'm pretty exhausted by the end of a long week's training -but I'm also sad to say 'goodbye' to friends A****, A****, B********, I***, L**** and S*****.

update The link I gave above is to a USA only site - that of the maker - which is very unhelpful indeed with regard to UK sources. I have researched this further and found an online store in Warwickshire selling them in the UK. Don't know the company, so this is more in the mode of a possibly helpful link than a recommendation ;-)

Posted by gje at 11:36 AM | Comments (0)

Virtual Hosting under Tomcat - an example

Tomcat supports "Virtual hosting", where you can direct several domain names to the same server computer / instance of Tomcat, and it will serve different content depending on which server you have asked even though they're on the same computer.

Here is the important part of the server.xml file that I used to set up an example yesterday afternoon:

<Engine name="Catalina" defaultHost="easterton">
  
<Host name="easterton" appBase="webapps"
  unpackWARs="true" autoDeploy="true"
  xmlValidation="false" xmlNamespaceAware="false">
  </Host>
  
<Host name="westerton" appBase="webapps2"
  unpackWARs="true" autoDeploy="true"
  xmlValidation="false" xmlNamespaceAware="false">
  </Host>
  
</Engine>

This Tomcat is serving a domain called "easterton" from the webapps folder, and a domain called "westerton" from the webapps2 folder. The domain names need to be correctly resolved by the browsing system (which will happen if you're using DNS, or if you set it in their /etc/hosts file). If the server receives an request for an unrecognised host, it defaults to "easterton".

Although I'm showing you virtual hosting on Apache Tomcat in thsi example, it's far more commonly used on Apache httpd - indeed, you'll probably find that more domains worldwide are served via a virtual host setup than via single computer hosting.

See the full Tomcat configuration file I was using here. For details of our Tomcat deployment courses, see here, and for Apache httpd see here

Posted by gje at 01:52 AM | Comments (0)

November 21, 2008

Every cloud has a silver lining

At first glance, a recession or depression in the economy slows things down and reduces the need for products and services, resulting in a need for us all to tighten our belts. But I've been taking a second glance, and I'm seeing areas where the slowdown (whether you use the "r" word or the "d" word) in general is giving a boost in some other areas. In the summer, when things were quieter than they had been a year ago, I heard of companies selling camping equipment who were reporting a huge upturn in business ... and no doubt that resulted in them putting more business out to their business to business suppliers - elements of growth.

One of our prospects for a private course wrote to me at the start of this week, and told me that his budget has been withdrawn - that they won't be taking their Python training plans any further at the moment. But then a delegate on this week's course, who booked quite late in the day, told me how their systems have got dramatically busier in the last two months to the extent that the training up of extra staff, including himself, in Apache Tomcat has been made necessary. So even in a a business that "first logic" would lead you to consider would be quickly and badly hit - training, conferences, and hotel rooms - there are shoots of fresh growth and new business.

I wish I had a crystal ball so that I knew ahead of times which areas will be going up and which will be going down. Now is an important time for us to look ahead, to be prepared to make adjustments to keep up and running and servicing our customers - and our new customers too - as they would wish over coming months and years. The period over Christmas and the New Year is traditionally a lean one, with both business visitors to Melksham and training course customers being virtually absent from a week or so before Christmas into the New Year, and then it only picks up slowly as people get back to work and restarted with their day to day work before they start looking ahead to the future ... and I don't see this holiday season varying widely from that. Yet even there we have an opportunity - to spend a little bit of available time that we haven't had during the year in recharging our batteries, and also in preparing to meet the demands of what out 2009 customer base will need.

Posted by gje at 06:46 AM | Comments (0)

Keeping on an even keel

Some (but not all) Open Source products have a numbering system where the second number is even for a production release and odd for a development release - so if you're looking to install one of these products on a live machine for customer use, you should make sure you stick with the even release even if a later odd one is available.

Products that currently use this system include:
The Linux Kernel (2.2, 2.4 now at 2.6) [learn]
Perl (5,6, 5.8, now at 5.10) [learn fundamentals] [learn advanced] [learn for web]
Apache httpd (2.0, now at 2.2) [learn]

Open Source software has an active developer community, and the mechanism requires that there is considerable exposure given to upcoming releases for things to be added, comments made, and code tested and improved by that community, with anyone welcome to play his / her role. For this reason, you'll see a wide variety of extra releases on all open source software that's almost completely absent from commercial software. Commercial software's upcoming releases need to be kept rather private to give the authors their commercial edge, and also to ensure that orders for the current release don't dry up when potential customers say "I won't spend my money on this version - I'll buy the next one when it comes out".

You may still see Apache httpd 1.3, and Perl 5.004 and 5.005, around from time to time. In each of these cases the odd number release was a production version prior to the adoption of the "odd/even" scheme. Apache httpd 1.3 in particular is now extremely mature, but also very commonly used indeed as people don't like to upgrade a web server that's working perfectly well. "If it ain't bust, don't fix it"

Posted by gje at 05:32 AM | Comments (0)

November 20, 2008

Virtual Hosts and Virtual Servers

Do you want to use a single computer to host many different web sites? There are no less than four quite common ways of doing this - each of which has its advantages and disadvantages.

At the top left of my diagram, you have virtual hosting. In this arrangement, all the domains hosted on a single server use the same IP address (machine number) and TCP port (service number within the machine), with the single piece of server software telling the domains apart by information provided by the client (browser) using a host: header. This is the cheapest of solutions, very commonly used indeed, and a fine solution for the majority of sites which will be quite small in nature.

At the bottom left of my diagram, you have virtual hosting with multiple IP addresses. In order to separate the different sites a bit more, you can use multiple IP addresses and have your single piece of server software telling the sites apart by the IP address (or the port number) on which contact is made. There are only occasional benefits with this approach, and these days - with IP4 address space running out - it can be regarded as a little antisocial to hog addresses.

At the top right of my diagram, you have multiple servers. Again using multiple IP addresses / TCP posts, but now running several servers on the same computer. You might do this is you have some Java based applications running Tomcat that you want to contact directly, and others to be fed via Apache httpd, or if you want to run two different versions of httpd (it's actually something that we do on one of our live servers, with some sites hosted by Apache httpd 2.0 and others by Apache httpd 2.2. It would be unusual to use this approach for multiple copies of the same server, as sharing a server helps in the balancing out of the load when one site is quiet and the other busy, and it saves duplicating services in computer memory too.

And at the bottom right of my diagram, you have virtual servers. These days, you can run complete "virtual computers" on a single physical box - a popular trend, illustrated by this diagram. Each web site owner thinks that he / she has a complete computer but in practise, there are a lot of sites running within a single system. The scheme helps on the physical maintainance, the energy footprint (less computers!) etc, and we'll be seeing a lot more of this in the future.

We cover the setup, configuration and maintainance of a varety of options such as the above on our Deploying LAMP applications course, next running early next month.

Posted by gje at 08:19 AM | Comments (0)

Comparison - with and without flash

Do you Use flash to make a bright scene darker? Not necessarily!

Here's a picture of Melksham Station taken last Sunday night with the available light:

And here's a picture taken a few seconds later, taken with flash:

Flash gives extra fill-in light in the foreground, and with camera adjustment it can actually cause the background to go much darker - quite the opposite of what many new photographers expect. You'll note that the only thing that's at all close to my camera in the these two shots - the blue box to the bottom right of the picture - is lighter in the flashed scene, but darker in the natural light scene. And that's reversed for the rest of the scene.

Flash is ideal for taking pictures of people / filling in close by scenes as it emphasises the close and darkens the background - sometimes to the extent that it makes a photograph that would have been impossible into one that's possible. For the scene above, though, it's counter-productive.

Footnote - there were no trains around at the time I took these pictures; the railway's guidelines for photographers state that you should not use flash to photograph moving trains and - as you can see from the pictures - it would be pretty pointless to do so anyway!

Posted by gje at 07:45 AM | Comments (0)

November 19, 2008

Shopping in Melksham

On Thursday, 27th November, Melksham is hosting a late night Christmas shopping event. Businesses that will be open until 8 p.m. include:

Amber Home Appliance Centre [link]
Andy York Photography [link]
Arthouse Cafe [link]
Castle News
Chinese Medicine Centre
Clinton Cards
Cobblers Bench
Cornerstone Coffee Shop
DJS Sports Retail & School Uniforms
Dorothy House [link]
Flowers in Focus
Gamingalore - video game store [link]
Helen Passmore, Handbags and Accessories
Iceland
Just Beauty Plus
KM Military Army Surplus and Outdoors [link]
Libra Hair Studio
Little Labels - Traditional toys, baby and childrens clothes and gifts
Marks Musical Instruments [link]
Melksham card and news centre
News Box
Peacocks [link]
Polly's Parlour - Antiques and Collectables
South of Heaven - Body art Clinic
Superdrug
The Factory Shop [link]
The Samovar Gift Shop
The Works Hair &Beauty
Tops Hairdressing
West Country Jewellers
Woolworth plc

... and of course we'll be open at Well House Manor as we are every weekday from 06:30 until late.

For more details, contact Melksham Town Council on 704187

(I have provided links to those establishments with their own sites and Melksham specific pages. If you are one of the establishments listed and would like a link added to a page I have not found, please email me - graham@wellho.net)

Posted by gje at 10:23 AM | Comments (0)

November 18, 2008

Some Linux and Unix tips

How to make a woman equal to a man

[trainee@easterton ~]$ man ls
[trainee@easterton ~]$ woman ls
-bash: woman: command not found
[trainee@easterton ~]$ alias woman=man
[trainee@easterton ~]$ woman ls
[trainee@easterton ~]$

In Linux and Unix, the man command gives you a manual page ... but there is no woman command. If you want to be politically correct, you can use alias to make woman equal to man

How big are my files v how big are my directories

[trainee@easterton jimbo]$ du -sk *
64244 httpd-2.0.63
5776 httpd-2.0.63.tar.gz
8 MyJava.class
8 MyJava.java
8 newfile
8 RevTempconv.java
15268 tomcat-connectors-1.2.26-src
1420 tomcat-connectors-1.2.26-src.tar.gz
[trainee@easterton jimbo]$ ls -l
total 7244
drwxr-xr-x 12 jimbo apache 4096 Apr 24 2008 httpd-2.0.63
-rw-r--r-- 1 root root 5896358 Apr 24 2008 httpd-2.0.63.tar.gz
-rw-r--r-- 1 jimbo apache 430 Apr 24 2008 MyJava.class
-rw-r--r-- 1 jimbo apache 115 Apr 24 2008 MyJava.java
-rw-r--r-- 1 jimbo apache 6 Apr 23 2008 newfile
-rw-r--r-- 1 root root 1557 Apr 24 2008 RevTempconv.java
drwxr-xr-x 9 jimbo apache 4096 Dec 21 2007 tomcat-connectors-1.2.26-src
-rw-r--r-- 1 root root 1442605 Apr 25 2008 tomcat-connectors-1.2.26-src.tar.gz
[trainee@easterton jimbo]$

The ls command reports on the size of each symbol in a directory, whereas the du reports on the size of each symbol and what it contains. This means that you should use du if you want to see how much a director contains, but ls if you're just interested in the size of the directory's header records!

Moving files and directories with multiple owners

[root@easterton ~]# cd /home
[root@easterton home]# mkdir ../gosh
[root@easterton home]# tar cf - | (cd ../gosh; tar xpf -)
[root@easterton home]# tar cf - cloudy dave gordon| (cd ../gosh; tar xpf -)
[root@easterton home]# ls -l ../gosh
total 32
drwxr-xr-x 2 cloudy apache 4096 Nov 6 18:09 cloudy
drwxr-xr-x 4 dave dave 4096 Jun 24 10:07 dave
drwxr-xr-x 3 gordon apache 4096 Nov 18 14:02 gordon
[root@easterton home]#

If you're moving a part of your file system around on a Unix or Linux system, you might be inclined to use cp -r and indeed that will work well if you want the ownership of the copy transferred to the user making the copy. But if you want to copy a part of the file tree and preserver ownership, you must to so as root, and use the tar command. In the example above, we have output from tar so stdout, then piped into another tar in another directory, unpacking with the -p option to preserve ownership.

These examples ... from our Linux Basics and Linux Admin courses - run yesterday and today, and next running early next month ...
[trainee@easterton ~]$

Posted by gje at 06:25 PM | Comments (0)


Useful link: Linux training

November 17, 2008

Melksham Chamber of Commerce and Industry

I'm passionate about Melksham - it's a great place to live and a great place to do business, and Lisa and I, although we were newcomers in 1999, feel greatly welcomed here. And I hope that we have given, and will continue to give, something back as part of the community. We bring visitors to the town through our training business - visitors who wouldn't othewise come to Melksham. We provide high quality business accommodation at our hotel for people travelling to work in the town. As a part of this we support local businesses - shop in the local shops, eat in the restaurants and take away from the takeaways too, and we're members of various local groups from Melksham 1st through the Melksham Railway Development Group, the Federation of Small Businesses and the Melksham Chamber of Commerce and Industry.

When we bought our first home and office in Melksham - in The Spa - we really didn't know Melksham very well, but we "lucked out". When we bought "Well House Manor" in 2006, we knew the town and what it had to offer, and it was a careful and conscious decision that we'll be here for the foreseeeable future, if not for a full lifetime. Basically, we really love the place (but having said that, we're not blind to some of the issues that face the town).

I select carefully - very carefully - what I take on in a role beyond just 'member'. And the things I take on are not necessarily the easiest, but they're things that I can commit to in that longer term. Thus, I'm very active with public transport around Melksham, but until now haven't been active as a more general advocate for the town - quite simply, I've not got the time / aptitude to get involved with a lot of the paperwork that would be involved if I were to be an officer of one of the groups, and there would be meetings I would miss when out of town. However - the Chamber of Commerce was looking for a new President - a role which involves the advocacy of the Chamber and the Town and its interests with other key organisations (governmental, business and trader, press, educational, public) and I stood for the role. I'm delighted that I wasn't the only candidate as a contested election gives an extra authority to the selected person, and I'm happy to report that the elected person was ... myself.

Th is new role fits very well with what I do / am doing already - not so much a case of "3 + 3 = 6" but rather "3 x 3 = 9" - I intend to make it good for the town and, yes, in the process it will be good for the TransWilts rail campaign and it will be good for the visibility of our business too. As I get into the role, you'll find more follow up threads here. Times ahead are interesting indeed; subjects at the heart of the business community include:
* County budgets and the squeeze away from the Market Towns
* Out of town stores
* High Pavement and town centre road improvements and closures
* The move to Unitary Wiltshire on 1st April 2009
* Waste Disposal
* A350 Access
* Growth and planning
* Public Transport
* The effect of the recession / depression on the town
* Boosting chamber membership
* Training and other benefits organised by The Chamber
(And these are in no particular order)

To complete this article - if anyone wants to contact me in this role they are very welcome to do so. My phone number is 01225 708225, and my email address is graham@wellho.net. And if you know what I look like (it's not exactly hard to find my picture on line!), you'll see me in the town centre a couple of times in most weeks - feel free to stop me!

Melksham Chamber of Commerce is a member of the Wessex Association of Chambers of Commerce

Posted by gje at 07:58 AM | Comments (0)

November 16, 2008

Ruby to access web services

If you want to use a Ruby program to access an RSS feed (or some other XML or HTML data), you can start with the standard Net::HTTP module ... full (working, tested) example here. That example "just" uses a Get method to get an RSS feed of the latest posts to the First Great Western Coffee Shop Forum - but you could easily tune it for other automated browsing.

If you take a look at the documentation for the class, you'll see it's straightforward to access data via the POST method too ... although it does require some background knowledge which we would love to teach you (if you don't know it ;-) ) on our Ruby Programming Course


I've been teaching Ruby over this weekend ... you may have guessed that, having seen the flurry of extra examples and tips posted, and I'm going to add in links to a final few examples here:

Ruby data formatting with the % operator / printf / sprintf

Ruby and $_, the -n option, topicalisation, etc)

Yield in Ruby or how to have two pieces of code passing data back and forth like generators in Python

Posted by gje at 05:03 PM | Comments (0)

MySQL database from Ruby - an example

Both MySQL and Ruby are huge subjects - the former being an excellent database engine and the latter a superb programming language. Yet although each individually is a huge subject, linking the two (i.e. accessing data stored in a MySQL database via a Ruby program) is so each that it's almost trivial.

Here's one way of doing it - my "Hello MySQL in Ruby" if you like.

1. Download the Ruby/MySQL module from http://www.tmtm.org/en/ruby/mysql/

2. Add the following lines (or equivalent) into your code:

require "mysql"
myconnect = Mysql::new("192.168.200.67", "trainee", "abc123", "forsale")
 
res = myconnect.query("select * from agents")
res.each do |row|

3. Enjoy!

The code loads in the module that you've downloaded (require), connects to the database engine and database (Mysql::new), runs the query (the query method on the connection object) and iterates through the result set.

The full source code of this example is here, and we cover the topic on our Ruby Programming course.

Posted by gje at 04:21 PM | Comments (0)

Ruby mixins, modules, require and include

A Ruby "mixin" is a way of adding extra code from a module into a class - thus giving the programmer the ability to share code between a number of classes in a way that's in addition to inheritance. So - in effect - it gives multiple inheritance.

In some ways, you can compare a mixin to a (Java) interfaces which defines extra methods that you MUST have in a Java class in order for it to complete (implement) an interface. However, a Java interface is all to do with meeting the rules of the extra methods that must be provided and doesn't bring in any code at all, whereas in Ruby there are no such rules to be enforced (Ruby assumes you know what you are doing) and the mixin is all about bringing in the extra code.

We've got an example of a module for use in a mixin at tcalc.rb and a file that contains a class that uses it, together with a test harness here.

I have also written an example today that:
• loads a module via require
• then imports its namespace via include
which are the same basic principles as used in the mixin ... and I'm going to paste the source code below. Remember that require and include do different things in Ruby to they do in Perl ... in Ruby, require is used to load in a file (which probably contains a module) and include then brings its namespace into the current namespace.

Example: here's the file taxcalc.rb

module Taxcalc
  VAT_RATE = 17.5
  def net(gross)
    net = gross / (100.0 + VAT_RATE) * 100.0
    return net
  end
  def tax(gross)
    tax = gross - net(gross)
  end
end

And here's a sample program that uses it

# Drag in the file ...
require "taxcalc"
 
# And merge in its namespace
include Taxcalc
 
amount = 70.50
# because of the include, no need to say Taxcalc::net, etc
shopkeeper = net(amount)
vatman = tax(amount)
print "#{vatman} to the taxman\n"
print "#{shopkeeper} to the supplier\n"
print "Tax rate is #{VAT_RATE}\n"

See also here for a further example of modules, mixing and comparators in Ruby.

Code example written to illustrate our Ruby Training Courses

Posted by gje at 03:38 PM | Comments (0)

Find the link

What do the following have in common?

1. Discount Spa Covers
2. Childcare products
3. Poland Translation Services
4. Telephone Headsets
5. Executive life coaching
6. Eye Surgery in Houston
7. Web Design Courses
8. London Flatmates
9. Film and television casting calls
10. Door handles
11. Bedroom Furnishings

They're all - each and every one of them - products offered by companies that I've been asked to provide links to ("link exchanges").

We have a successful site such - with around 130,000 hits per day during the week, and around 70,000 hits per day at the weekend. And it seems to me that others want to share in our success. And I'm all for co-operation, but targeted co-operation rather than participating in Link farms. You'll note that I put in links to local businesses on our web site, I tout products that I like and use (with links too) and I encourage our customers to do the same.

Many of the requests for links that I've listed above included the sentence "PLEASE NOTE THAT THIS IS NOT A SPAM OR AUTOMATED MAIL, IT'S ONLY A REQUEST FOR A LINK EXCHANGE." in their email. Yes, sure! Pull the other one - it's got bells on it!

The illustration? Something else that's utterly irrelevant to our activities as a training provider and hotelier in Melksham. It's a picture of the waterfront at South Queensferry, on the Firth of Forth

Posted by gje at 11:13 AM | Comments (0)

Ruby Programming Course - Saturday and Sunday

We're so busy during the week at the moment that I'm running an extra Ruby Course this weekend. The main use of Ruby is within "Ruby on Rails", but our course concentrates on the language itself and so it's suitable for people who are using RSpec, cucumber and Watir as well as Rails.

Here are some links to new Ruby examples added this morning, from yesterday's practicals:

A simple read - calculate - print example in Ruby

Common Ruby Pitfalls

Alternative ways of writing loops in Ruby

Loops and conditionals exercise

Sample class and test program showing common object features in Ruby

Counting events in a file using a Ruby hash

Embedding variables in strings in Ruby

Posted by gje at 08:26 AM | Comments (0)

November 15, 2008

Keys to friendless churches

I don't know exactly how I found their web site - but I have come across the Friends of Friendless Churches. And I read ...

The forlorn tower at Saltfleetby was taken on by the Friends in 1976. The tower, which dates from the 15th century, is the only surviving part of the church, so there is no need for a key. If you would like to visit the church and need details of keyholders, ... , please telephone our office on: ...

I'm sure they're very earnest people and they're not trying to be funny - but once they befriend a church, it's no longer friendless, so surely it should be taken off their books. And why exactly might I need a key?

Posted by gje at 03:19 PM | Comments (0)

Hiding a MySQL database behind a web page

"Keep the browser simple - with a single route in (http) to a server." That's the philosophy behind the web and one of the things that's made it a huge success. It means that a straightforward browser can contact a single server, and Joe Public, Joan Whiting and Mahatma Ali can all view content. But that means that the complexity of storing and accessing data has to be dealt with on the web server, and the straightforwardness of the browser interface is counterbalanced by some quite complex server side systems. It makes sense, really - for every 1000 browsers there might be one server, and it's far better to have one complicated system that a thousand.

Yesterday afternoon, I put together a demonstration showing these various server side elements. A browser, contacting a web server. And then, behind the scenes, the web server running a Perl program via the CGI interface, and that Perl program in turn contacting a MySQL database server for the actual data. And another couple of sample programs (at the proof of concept level) to add more data to the tables. It's rather a long demo so that - rather than post it all here - I've put a full description in our solution centre here and I've put all the source files here. You can even try out the general display page, the Add Operation Page and the Add Patient pages ... although (for server security) I've commented out the line that would save your additions to the tables on our live server I'm not going to risk people entering patients who's names read like adverts!

The demonstration uses the example of medical patients and the operations that have had in two MySQL tables, joined to produce the final results, but the same principles would apply to estate agents selling houses, and to railway trains making station stops!

Posted by gje at 01:32 PM | Comments (0)

November 14, 2008

Recession? Depression?

09:10, Friday

There's three guests eating breakfast in "The Whitworth". A meeting going on in the Coffee area, and another meeting in the Library. Groups in "The Wilts" are still chatting at the end of the BNI meeting, and I'm typing these notes in "The Berks" while I wait for my delegate. Room 3 is open / on show (and to provide an extra loo). Room 1 is checking out today, and room 4 has extended a further night. I understand that Lisa is confirming a booking for next week's course, and the hotel arrival that booked on line last night to arrive on the last day of 2008 and leave on one of the first days of 2009.

I think the recession that we're hearing so much about is patchy and, this morning, we're not in one of those patches!

Posted by gje at 09:07 AM | Comments (0)

Spa Road Garage and Convenience Store, Melksham

It's "Children in Need" day, ... a fact I was reminded of when I popped into our local garage on Spa Road in Melksham

Bruce and his team are always very welcoming when Sharon, Chris or myself pops in to buy the morning papers for Well House Manor (no standard order - we tailor to our guests) and I'm impressed by the cheerfulness of the team, their willingness to help (and to joke at an unreasonably early hour in the morning!). I've also been impressed by Bruce's tireless involvement in the Rotary.

So, thank you Bruce, Maid Marion, Superman and the St Trinian's pupil for giving me a smile this morning - and for being such a good neighbourhood store and garage.

Spa Road Garage (a Spar store) is open 7 days a week from 06:00 to 22:00 - just two doors up from us - selling groceries, papers, fuel and much more. They're so good that we don't even try to complete with those little things our visitors might need - we know they'll get a warm welcome at Spa Road Garage, Melksham from Bruce and his team.

Update - 17th November. Bruce and his team raised £505.05 for Children in Need - Congratulations and thanks to everyone at Spa Road Garage.

Posted by gje at 07:54 AM | Comments (0)

Wiltshire Council says - part 2

"We have the following options available for lunch ... Baguettes ... India ... Chinese ... Baked Potatoes ... Greasy Spoon ... McDonald's ... Fish and Chips"

That's not untypical of what we stay during first morning of a course, allowing our delegates to make a selection ... and almost inevitably, the group will come a decision and everyone's happy. And so are we - because we failed to mention the availability of the French Restaurant (breaks the budget), the Pubs (take too long) and the Pizza and Kebab places (never believe orders that are phones in at lunch time, so major nuisance in waiting to our staff)

You can call this "engineering the decision" if you like - and I think it's fair enough for us to do so as we've specified our remit and product. But where such engineering is done by a body that's there to represent the people and take into account all requirements in an area, it gives me serious misgivings. Let me give you an example from Wednesday evening, when we went to the budget consultation at Wiltshire (County) Council.

Speaker after speaker from The Council talked about "Salisbury, Trowbridge and Chippenham". Like a mantra - consistent to the extent that it can't have been a co-incidence. From Council Leader Jane Scott (from Chippenham) with words of agreement from Keith Robinson (who works for her in Trowbridge) ... from the business development manager through the chief financial officer, via the guy in charge of the environment. Every council employee who spoke, in fact.

I've news for Keith and Jane and their team - there's more towns than those in Wiltshire, and they're responsible for them ... even if they don't live in them themselves. Have a look at these population counts (2001 Census, rounded, from the Council's own web site:

40000 Salisbury
28000 Trowbridge
28000 Chippenham
--- Where the council wants to stop? ...
Total population - 96,000

20000 Melksham
17000 Warminster
16000 Calne
13000 Devizes
11000 Westbury
11000 Corsham
11000 Wootton Bassett
10000 Bradford-on-Avon
Total population - Wiltshire's second class towns - 109,000

--- And not to forget ... the likes of Malmesbury ... Marlborough ... Amesbury ... Cricklade ... Durrington ... Lyneham ... Tidworth ...

There was a fear that when Wiltshire went Unitary, perhaps one of the five towns of West Wiltshire would actually be large enough to get any attention - that Salisbury, because it's the largest and City, Trowbridge because it's the County seat, and Chippenham because it's the Council Leader's town would - like bullies in the class - get all the attention and investment. Perhaps I'm seeing signs of this already - even before the new council actually comes into existence. We need to raise the voice of Melksham .. of Warminster ... of Calne, Devizes, Westbury, Corsham ...

Posted by gje at 07:08 AM | Comments (0)

November 13, 2008

Wiltshire Council says - part 1

Last night, Lisa and I attended the annual budget 'consultation' evening arranged by the Wessex Federation of Chambers of Commerce with Wiltshire (County) Council. It was our second year at the event ... last year we had come away very depressed indeed, but this year was rather better - partly because we do see some good and positive in what is being said and done, and partly it must be admitted because we went along fearing a repeat performance.

This is going to be a 'big' year. "1C4W" is the headline and it means "1 Council for Wiltshire" - with one tier of local government being swept away and 5 councils being swept into one. And it was the upper tier (the larger council that in essence is taking the others over) who's budget 'consultation' we went to. (You'll note I'm quoting 'consultation' because, really, it wasn't - it was a case of them telling us and asking only for a few limited inputs).

I agree that we have had too many layers of local government - that it's been too hard to know which particular level to go to about certain issues, and that the layers have been inefficient and duplicated. And I hear that "big is beautiful" and that minnows would get squashed or overlooked. However, I think I would rather have carried on working with the team from layer that's being scrapped ... but realistically that's now water under the bridge, and we must work with the county people in sole charge. What did they tell us last night?

1. That their annual spend is projected to be just over 800 million pounds, and how that spend it to be apportioned.

2. That it's going to be a tough year (and why). I seem to recall them saying this last year too, and coming up with a string of reasons, some the same as this time and some different. Curiously (?), some of this year's reasons such as low interest rates which means less money coming in from investments have me wondering "but that wasn't the case last year" and thinking that we're only being told the reasons that things are tough - just being given the bad news, and not the good to go with it to make a rounded picture.

3. That it wasn't their fault that they had money in Iceland (and in any case they technically didn't, because it was the UK subsidiary of an Icelandic Bank) and are currently owed 8 million which they are "hopeful" to get fully back.

4. They want to do lots of good things for Salisbury, Trowbridge and Chippenham ... and not to forget the rural areas. Subject to be continued tomorrow ....

Posted by gje at 06:24 PM | Comments (0)

November 12, 2008

Melksham Chamber of Commerce, or the FSB

Yesterday, my email box received a number of messages concerning the Federation of Small Businesses, where the National Executive have fired the solicitor running their disputes and disciplinary procedure because the D&D committee came up with the "wrong" verdict.

And yesterday evening, the Melksham Chamber of Commerce and Industry met at Well House Manor, to elect its committee for the coming year, a new president, and to listen to the Mayor of Melksham talking on the local issues of the closure of a main shopping street for several weeks, and on how the town council and others are working to help promote late night shopping evenings to boost trade, and other councillors went through next year's Melksham food festival, and updated us on the move to a Unitary Authority and how it will effect local representation.

What a contrast! The sacking of solicitors at the FSB and all the associated infighting has turned a once-useful local organisation into something of a laughing stock, and the Chamber of Commerce, which suffered something of a split a few years ago when the town centre traders and other businesses in the town disagreed on out of town developments, is coming very much back into its own again - and long may it continue to grow.

I'll be at a Wiltshire Council meeting this evening. Need I even tell you that's it's under the arrangement of The Chamber rather than the FSB?

Posted by gje at 12:16 PM | Comments (0)

November 11, 2008

Dynamic code - Python

When I learned to program, named blocks of code (subroutines and functions) were built into each program and weren't things you could change at run time. But these days, in some languages like Python it's very different and you can write code that includes dynamic functions and methods - after all, in Python everything is an objects (including code) and you can change objects as your program runs.

What does this mean?

Well - here's a piece of valid code:

if kids < 3:
  def more(current):
    return current + 3
else:
  def more(current):
    return current + 8

and in that code I've defined a function in two different ways depending on the value of a variable. I can also redefine it later on in my code if I wish - you can see that in a full example here.

Is this capability a good idea? First comment - be careful how you use it, as it's open to abuse. BUT, yes, it can be very effective. For example, a complete application such as Plone can have default functions defined and they a user-supplied piece of code can replace a named function - a really useful, practical, and powerful facility.

Posted by gje at 11:11 PM | Comments (0)


Useful link: Python training

November 10, 2008

Pascals Triangle in Python and Java

There are certain "party pieces" that I have during courses ... and on my Java Courses, a program to generate Pascal's Triangle in an array of arrays is one of them.

One of my delegates on today's Python Course suggested this as an exercise ... and here's a link to the source. Turns out to be even more elegant than the Java solution, which you can see here

Posted by gje at 05:50 PM | Comments (0)


Useful links: Python training, Java training

November 09, 2008

Guests doing a bunk?

Hotel guests, due to check out this morning, not down from breakfast at the time they had estimated. All quiet - very quiet - on the bedroom front. Their car missing from the car park (I looked up the registration to check). Yes, I was concerned (but not overly so; as a matter of course, we have booking guarantee details and can charge in the event of a no-show or an abscond-without-paying).

It's the waiting and wondering that keeps the tension going and the blood pressure high.

Are they there and just late down?

Looking up at the room from outside, there's condensation inside the window. A good sign; it indicates it is, or recently has been occupied.

And within 30 minutes the guests appear. It seems they were out with local friends last night, and had a few to drink. Rather than driving back, they got a lift ... then overslept (and deeply so) beyond the time they had planned. There's usually a perfectly logical explanation and good on them for leaving the car elsewhere late last night.

A happy breakfast, a chat about today's plans ... and their friends arrived to collect them a little later. "May we show them our room" our guests ask. "By all means" says I, smiling ... and a worry of an hour earlier had turned right round into an opportunity for a little bit of marketing. "Have a cup of coffee too ..." says I.

Posted by gje at 12:46 PM | Comments (0)

November 08, 2008

Python Regular Expressions

Python supports string pattern matching to regular expressions, using Perl style regular expressions.

The re module - loaded via
  import re
brings the appropriate elements into your program ... ready to use.

Patterns that you want to match against are called Regular Expressions and are created as objects from strings using the re.compile method. For example
  looklike = r'([a-z]+)\.([a-z]+)\[([^\]]+)\]'
  el_matcher = re.compile(looklike,re.IGNORECASE)

And you can then use the compiled regular expressions to find parts of data strings that match the pattern you have defined:
  zz = el_matcher.findall(thing)

If you're new to regular expressions, you'll probably find the definition strings - the regular expressions - a bit overpowering at first> but as you read into them the become easier. Let's analyse the major elements of the one above:

[a-z] A letter in the range a to z
+ One or more (of the previous item)
\. Literally a full stop
[a-z] A letter in the range a to z
+ One or more (of the previous item)
\[ Literally a [
[^\] Any character which is NOT a ]
+ One or more (of the previous item)
\] Literally a ]

Read that against sphere.v[32:58] and you'll see that it does indeed meet the description ... the extra round brackets in the original regular expression show Python which particular parts of the match are to be stored into separate objects that are returned from the match so that use can be made of them in subsequent lines of the program.

The complete example that I've been quoting from above - which matches a string of the type that may be produced by Autocad's Maya, for example, may be found here ... and we cover regular expressions on many of our courses (including our Python course, and indeed we run a special Regular Expression Course for those who need detailed coverage.

Posted by gje at 07:35 AM | Comments (0)


Useful link: Python training

What are exceptions - Python based answer

How do you check for run time errors in your program? You'll include tests with if statements in almost every program you write, to ensure that user entered data is reasonable / as you would expect ... but you will also need to do more that that. You'll need to check whether a system function has run correctly - "Did that file open" type questions. One very commonly used approach to error checking of this sort is to call functions that return a special value (a cardinal value) in the event of an error - something that can never be a correct answer - and check for that value after every call. You'll see that approach used very widely indeed, especially in older languages.

But there's an alternative - the exception. With exceptions, you write code in a block that says "try" to perform a particular task, and if something goes wrong an exception is thrown and the code jumps to an exception / error recovery block. What are the advantages of exceptions:

a) There's no need to use cardinal values that may turn out to be not so improssible in the normal run of events anyway

b) You don't have to program for every possible error individually - you can lay out a safety net to catch any errors that occur within a certain area of the code irrespective of what they are

c) You have a need mechanism for correcting and bringing the code back together rather than having to code with lower level if tests.

Here's an example in Python. For clarity and completeness, in this program we raise the exception ourselves in the howlarge function rather than allowing the built in function called list to do so:

def howlarge(mylist):
   if isinstance(mylist,list):
      size = len(mylist)
   else:
      raise TypeError,"Only works on lists"
   return size

The main code for this short example is a single try block, in which we call the howlarge function multiple times. It will fail on the fourth of five calls, since the function traps any calls in which the object passed to it is not a llist - so you get three sets of results followed by an error message. You'll notice that if an exception is thrown, the code jumps to an appropriate handler and the rest of the try block is skipped.

try:
   print (howlarge([5,6,5,6,7]))
   print (howlarge([5,6,7]))
   print (howlarge([]))
   print (howlarge(14))
   print (howlarge([5,6,7]))
except StandardError,e:
   print "Oh - never mind ...."
   print e
print "Program Completed"

Once the except block has been completed (or the try block completed if no exception was thrown), the code runs from the end of the structure - in this case simply stating "Program Completed"

Dorothy:slee_liv grahamellis$ python oy
5
3
0
Oh - never mind ....
Only works on lists
Program Completed
Dorothy:slee_liv grahamellis$

Full source here. You'll find more on exceptions in Python, exceptions in C++, exceptions in Ruby and exceptions in Java here.

Posted by gje at 06:51 AM | Comments (0)


Useful link: Python training

November 07, 2008

Is it worth it?

There are times that I wonder "is it worth it ..." with some of the things that I do. The world won't crumble if I miss the blog for one day, and the forum is quiet - is it read? Is it worth it?

But then ... I just look at today. Kevin and Ted are posting on the forum. And as I look across to it, writing this short note, I find a useful post with suggestions from Keith. Marion - in spite of all that's going on for her - has dropped me a note to say how much she enjoyed the Obama piece, Andrew is delighted to sign up for our other forum from Vegas, Justin has got back to me with a follow up on a note that I had just answered - 6 months late - because he had gotten spam trapped, Angie has dropped me a suggestion for our training, Edward has written by email with follow ups to an archived forum item he found useful, and Alok to whom I send a reply which (when I look back at it) I'm ashamed of has - never the less - sent me a polite thank you. And there's Crystal and Brad and Marieke and another Andrew and Nicole, Emily and Laura, Bruce and Neil and Martin ...

Yes - many times over - it IS worth it. Thank you, everyone, for your support of the Opentalk Forum, the Horse's Mouth, our courses and our other activities. I'm deeply touched.

Posted by gje at 10:14 PM | Comments (0)

November 06, 2008

List Comprehensions in Python

How do you perform an operation on every member of a list, producing a new list? A List Comprehension in Python is a structure in which a for loop is written within a list's square brackets. Its purpose is to allow the programmer to write short code that's used to transform each element of a source list, generating a new list without the need to append new items one by one to that new list. Here are some examples:

squares = [x*x for x in range(10)]
print squares
# result - [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

and

breakfast = ["Orange Juice", "Cereal", "Actimel"]
size2 = [len(x) for x in breakfast]
print size2
# result - [12, 6, 7]

One of the more conventional alternatives to a list comprehension is a map function call (but that's more limited). Here is that example we have just see re-coded in the form of a map for comparison:

size1 = map(len,breakfast)
print size1
# result - [12, 6, 7]

But here are some examples that wouldn't be so easy with a map - if (for example) you wanted to run a method on each object in a list, rather than a function on each member:

shout = [x.upper() for x in breakfast]
print shout
# result - ['ORANGE JUICE', 'CEREAL', 'ACTIMEL']

And here's another feature - you can add an if clause onto a list comprehension which allows you to select (filter out) certain records if you wish:

shout = [x.upper() for x in breakfast if x != "Cereal"]
print shout
# result - ['ORANGE JUICE', 'ACTIMEL']

Full source code of this example - here

Posted by gje at 06:21 AM | Comments (0)


Useful link: Python training

November 05, 2008

Barack Obama wins US Predidency

Congratulations to Barack Obama, who has won a decisive victory in the Presidential Election in the USA. And a few words too for John McCain, who was very gracious in his speech of concession - almost the John McCain as I had seen him as the honourable maverick years ago, a John McCain that seemed to have got lost these past 18 months into something a lot less palatable. But this is Obama's night, and his four (or eight) years.

As a British Citizen, I had no vote (why should I have had? because the role of the US president is a worldwide one, perhaps?) and didn't know the details of the candidates, but I see much to admire in this election - many positive aspects.

I see a mould being broken - the future president is not another old white male who can trace 90%+ of his ancestry back to the Mayflower and her successors. It doesn't really matter whether the new guy has blood that's African, Chinese or Hispanic or (as is the case) a mixture. What matters is that you have someone who can inspire and lead - as you've seen him do in his winning of the nomination (against a strong candidate in Hilary Clinton) and then against John McCain. I wish him well in that leading.

I see a win by a comfortable margin - not only on electoral college votes, but also winning in the popular vote. And that means you don't have a question mark over the leadership from the very start as you had with George W. And I see that comfortable margin achieved on a very high turnout. That's fabulous - it gives further strength and authority to a system that had, perhaps, become apathetic in parts.

I see a new leader who talks about may aspects, and talks about them in a worldwide and not isolationist way, and talks about international affairs in such a way that I feel that his first solution isn't going to be to go marching into countries with the troops! And I hear of a campaign that's been financed largely by internet and small private donations - whilst there are question marks over just how much money has been spent, I'm mighty glad it hasn't come from a handful who might then be looking to act as the puppeteers.

There's a lot to be done. An unstable financial market that has overstretched itself and caused real problems. Security issues in the Middle East. Rebuilding bridges with world neighbours, and more. And there's a high expectation - so very high that the question is asked "can he do it?" I don't know the answer, but I do know that he HAS won two gruelling rounds and comes into the third round, to be played over four years, with a record and experience that tells me he has a darned good chance. Mind you, it's likely to be a very short 'honeymoon' once he's into the thick of it in January.

Call me emotional, but I was very glad to see that he took Florida where my wife lived for many years, and Virginia where my sister in law lives. I wish him well for them, for all other Americans, for everyone else in the world - and I hope he finds himself just a little time for friends and family to help keep him crisp, fresh, enjoying his role, and with his feet on the ground.


A footnote for anyone who stumbles across this article, and wonders who I am to be passing comment. I'm just me; I have no special authority to pass comment on American Politics and I'm just expressing my views - and good wishes. Call it the view of a typical Brit if you like.

Graham Ellis, Liverpool, early on 5th November 2008

Posted by gje at 08:06 AM | Comments (0)

Optional and named parameters in Python

When you're calling a named block of code (either a function or a method in Python terms), you'll pass in a number of parameters. Some of those will be mandatory - needed every time. Some will be optional, but frequently used, and others will be wanted on very rare occasions indeed and selected from a potentially huge number of possibilities.

Calls to a Python function (and the matching declaration) normally start with the mandatory parameters, followed by the optional but most-often-wanted ones, and finally the less common ones.

• There are some straightforward functions defined and called in this example (opens in new window, as do all following source links)

• There are some fucntion calls making use of optional parameters, and calling functions in a separately loaded file here and the function file is here.

• There's an example of "call by name" where the caller tells the function which parameter is which, and also an example of a call that puts a whole load of values into a single list (like sponging up remaining paramaters)