Perl state variables

Perl 5.10 added a new class of variables ‘state’ that are similar to ‘my’ in scope but are only initialized once. Even inside of a subroutine a state variable will only be initialized on the first call to the subroutine and will maintain it’s last value between calls. A simple example is the easiest way to show how state works. In the code below the two subroutines are identical except that the variable $countval is declared with my in the first sub (non_state_count) and with state in the second sub (state_count). This means the $countval variable will be initialized on every call to non_state_count and will not maintain it’s value between calls. In state_count it’s the opposite and $countval will initialize only once and then maintain it’s last value between calls.


#! /usr/bin/perl
use feature qw(state);

print "Result of calls to non_state_count\n";
for ($i = 0; $i < 10; $i++) {
    print non_state_count() . ' ';
}
print "\n notice that the variable countval is reinitialized on every call\n";

print "Result of calls to state_count\n";
for ($i = 0; $i < 10; $i++) {
    print state_count() . ' ';
}
print "\n observe that the variable countval now retains its value between calls\n";

sub non_state_count {
    my $countval;
  return ++$countval;
}

sub state_count {
    state $countval;
  return ++$countval;
}

You should see the output of the script as:

Result of calls to non_state_count
1 1 1 1 1 1 1 1 1 1
notice that the variable countval is reinitialized on every call
Result of calls to state_count
1 2 3 4 5 6 7 8 9 10
observe that the variable countval now retains its value between calls
Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.

JDK 7 - Try with Resources

JDK 7 has several enhancements to the try-catch construct. Try with resources allows for ensuring that resources are closed and freed up without the need to explicitly call the close function. Any class implementing java.lang.AutoCloseable can be automatically closed without the need for a finally section in the try block.

The syntax is a try with parens and the resources to automatically close out inside the parens.
try ( resources ) { code } catch (exception) { }

snippet 1 shows the syntax for try with resources:


try (
    BufferedReader reader = new BufferedReader(
        new FileReader("c:/dev/jdk7test/t1.ofx"));
   BufferedWriter writer = new BufferedWriter(
        new FileWriter("c:/dev/jdk7test/output.txt"))
   ) {
         // read and write
     }

Another change to try is that the catch can now handle multiple exception types in one block. Multiple catch blocks are optional and still work fine if you prefer to separate the handling. Just separate the exception types with | .

Snippet 2 catch with multiple exception types:


catch (java.io.FileNotFoundException | java.io.IOException ex) {
    System.out.println(ex.getMessage());
}

Lastly here is a small simple class that shows both features in action.


package jdk7test;
import java.io.*;
public class Jdk7TryWithResourcesTest {
    public static void main(String[] args) {
        Jdk7TryWithResourcesTest test = new Jdk7TryWithResourcesTest();
        test.execute();
    }

    public void execute() {
        try (
                BufferedReader reader = new BufferedReader(new FileReader("c:/dev/jdk7test/t1.ofx"));
                BufferedWriter writer = new BufferedWriter(new FileWriter("c:/dev/jdk7test/output.txt"))
            ) {
            String line;
            while ((line = reader.readLine()) != null){
                writer.write(line);
            }
        } catch (java.io.FileNotFoundException | java.io.IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
}
Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.

JDK 7 - use Strings in switch statements

JDK 7 adds the ability to use String objects as the case in switch blocks. It’s not exactly an earth shattering addition but I find it quite useful in avoiding long if-then chains. Plus the release docs claim that using a switch is more efficient.

At the bottom of this post is a small java class that provides a complete example of use. Here is the part we’re concerned about. The switch takes a String argument that should be the abbreviated name of a month and sets the return value to the quarter of the year that month is in.


switch(monthIn) {
            case "Jan":
            case "Feb":
            case "Mar":
                retval = "Q1";
                break;
            case "Apr":
            case "May":
            case "Jun":
                retval = "Q2";
                break;
            case "Jul":
            case "Aug":
            case "Sep":
                retval = "Q3";
                break;
            case "Oct":
            case "Nov":
            case "Dec":
                retval = "Q4";
                break;
            default:
                throw new IllegalArgumentException("Invalid Month argument: " + monthIn);
}

That’s a pretty geedunk example but it shows the functionality and is simple to read/understand. Here is a complete class that shows the same switch statement in use:


package jdk7test;
import java.util.Calendar;

public class Jdk7test {
    public static void main(String args[]) {
        Jdk7test test = new Jdk7test();
        test.execute();
    }

    public void execute() {
        String[] strMonths = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
                                            "Sep", "Oct", "Nov", "Dec" };
        Calendar cal = Calendar.getInstance();
        try {
            String monthName = strMonths[cal.get(Calendar.MONTH)];
            String quarter = getQuarter(monthName);
            System.out.println("Month: " +  monthName + " is in quarter: "
                               + quarter);
        } catch (IllegalArgumentException e) {
            System.out.println("The month sent to getQuarter was invalid");
            System.out.println(e.getMessage());
        }
    }

    public String getQuarter(String monthIn) {
        String retval;
        switch(monthIn) {
            case "Jan":
            case "Feb":
            case "Mar":
                retval = "Q1";
                break;
            case "Apr":
            case "May":
            case "Jun":
                retval = "Q2";
                break;
            case "Jul":
            case "Aug":
            case "Sep":
                retval = "Q3";
                break;
            case "Oct":
            case "Nov":
            case "Dec":
                retval = "Q4";
                break;
            default:
                throw new IllegalArgumentException("Invalid Month argument: " + monthIn);
        }
        return retval;
    }
}
Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.

JDK 7 release candidate now available

Build 147 for JDK 7 is now available with the goal of a generally available release later this month. Some good resources are:

As I test out the release I’ll do some posts on new features.

 

, , ,

Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.

Perl 5.12 using each with arrays

As of version 5.12 perl now supports using each with arrays and hashes both. For our pm project we should get in habit of using it. No need to rewrite any old code.

In practice it’s very much the same as use with hashes. each still returns 2 results with the first one being the index in the array instead of the key for a hash. This lets us use the convenience of a while loop to step through the array getting both the index and value.

Short simple example:


my @arr = qw(test1 test2 test3 test4);
while (my ($idx, $val) = each @arr) {
	print($idx, $val);
};

gives output:

0, test1
1, test2
2, test3
3, test4

The iterator here will respond to changes in the array inside the while block. I really don’t recommend changing inside the loop but just as an example:


my @arr = qw(test1 test2 test3 test4);
while (my ($idx, $val) = each @arr) {
  if ($idx == 3) {
    push @arr,"test5";
  }
  print("$idx, $val\n");
};

will output:

0, test1
1, test2
2, test3
3, test4
4, test5
Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.

Quote of the day 26-March-2011. The power of the washing machine.

Hans Rosling always gives great presentations and this one is really excellent as he discusses energy uses across economic class lines. Using his personal expierence of how the washing machine affected his life, he touches both sides of the issue. The ending sentences are some we should all remember.

“Thank you industrialization. Thank you steel mill. Thank you power station. And thank you chemical processing industry that gave us time to read books.”

Watch the whole video, it’s short and you’ll like it.

Jack Daniels and the deficit

Needs nothing added.   Video by10000Pennies

Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.

Quote of the day 3-3-11

Russ Roberts has a great short piece Don’t follow the money on the buy local movement at Café Hayek. His ending sentence is the best one line summary of the buy local scene I’ve found.

We have tried buy local before. It is called the Middle Ages.

Murray N. Rothbard’s Austrian Perspective on the History of Economic Thought

Rothbard’s massive book on the progression of economic thought is not an easy read and the sheer size of the work is no doubt intimidating to many. Nonetheless, it is a trove of knowledge and insight I recommend to all. Mises.org now has both volumes combined into one EPUB and the 2 volume set of PDF files are still available also. One of my favorite features of the history is how Rothbard demonstrates that progress is not always forward but that knowledge of a subject also declines and starts down many paths that turn into dead ends. Reading this book will not only take you on an incredible journey as humans try to understand how to deal with the inevitable scarcity of resources to fulfill our unlimited desires and needs but will also give you great insight into how human understanding progresses, declines and staggers along the way to knowledge.

Both the PDF and EPUB (my recommendation) are available at the Ludwig von Mises Institute for free download.

Installing Perl under your home directory

The question of how to do a local install of PERL comes up now and then. The truth is it’s quite simple if you have a normal set of build tools installed. GCC, make, etc. I will walk through the steps here on doing the build and install.

  1. Decide where you wish to put the install. For example my work box has Perl 5.10 installed for the operating system but I use 5.12 to develop. To do this I have version 5.12.2 installed into the directory tree at ~/tools/perl .
  2. Download the version source you wish to install from http://www.perl.org/get.html . At the time I write this 5.12.2 is the latest stable version.
  3. Uncompress & untar the source into a work directory and cd into the work directory
  4. Now the important part. We must pass to Configure the value of the directory we want to install to. This is passed as the prefix . For example ./Configure -des -Dprefix=/home/rcuddy/tools/perl
  5. Perform the make steps.
  6. Make
  7. Make test
  8. Make install

This will build Perl and install it into the directory you set with the prefix option for Configure. If you want to make this your default Perl then edit your path setup to put the perl/bin directory in front of the system paths. Example: PATH=~/tools/perl/bin:$PATH

Installing extra modules to your new tree is also very easy. Just make sure the cpan or cpanp you run is from the bin directory of the new tree. If you setup the new install as your default Perl then just run them as normal and the operations will be performed on the local install.

I told you it was easy :)

P.S. Yes it is possible to have any number of different versions installed this way as long as you use different prefix settings and of course are careful about calling the right binary.

Standard disclaimer - At the time of posting I believe all information contained to be accurate but there is absolutely no warranty or guarantee.