Category: Perl

 | Perl | 6 Comments

Whenever starting another Perl project, the very first command you should run better be the following:

$ module-starter --module=My::Module --author="[your-name]" \ 
                 --email=[your-email] --builder=Module::Install

This provides the developer with a basic environment for writing solid Perl code, e.g. a new directory called My-Module with all the good stuff ready for use:

MANIFEST
README
ignore.txt
Makefile.PL
Changes
lib/My/Module.pm
t/pod-coverage.t
t/pod.t
t/00-load.t
t/boilerplate.t
t/manifest.t

After that it's the following, and off you go.

perl Makefile.PL
make
make test
make install

Life couldn't be easier could it?

 | Perl | 4 Comments

These days it is not very often that a new and exciting Perl book comes along. That's why I was very excited when my Amazon.co.uk box arrived by post the other day.

I gleefully ripped the cardboard box open and held in my very own hands the recently released Effective Perl Programming, 2nd edition. Twice the thickness of the first edition and jam-packed with even more useful information.

This is a fantastic read which covers just about every aspect of Perl needed to program like the pros. Myself having had quite some experience with Perl was pleasantly surprised to learn new and interesting tidbits and other gems of information. Since having already read the book from cover to cover a couple times, I now keep it close at hand for reference purposes.

This wonderful book can be useful for beginners although it's pretty detailed and technical at times, but it's real use I believe is for experienced folks like myself who want to refresh their memories, extend their horizons, and recharge their enthusiasm for exploring new and possibly dangerous territories.

Here's an example of one of those one-liner gems, see if you can figure out what it does:

@a[ map { $_ * 2 + 1, $_ * 2 } 0 .. ( $#a / 2 ) ] = @a

From Chapter 2, Item 17 we find the following quote which appropriately summarizes one of the important philosophies: Perl is a "human" language in that it has a context-dependent syntax.

Finally, here are some other interesting places you might want to explore:

I can recommend you get the book also. Have fun.

 | Perl | 3 Comments

I really like programming languages that allow you to think less without compromising the quality of your coding practices. Take for instance the new smart match operator '~~' which was introduced in the latest Perl releases.

if ( '123.0' ~~ 123 ) { ... } # String and number: TRUE

You don't have to keep trying to remember if a given scalar is a string or a number or 'numish' (both), sometimes wrongly using the standard operators ( eq, ne, lt, ==, >= ) in the wrong places causing bugs which are hard to track down.

Don't forget to enable this functionality by including the following in your code:

use 5.010;

Or you can enable the feature by calling Perl with the '-E' option at the command line.

 | Perl | 0 Comments

Read this from beginning to end, and you then tell me with a straight face that it hasn't completely changed your life.

I believe it is high time that we stop dilly-dallying around, that we face the future for what it is, for what is was meant to be, and take the challenge.

for 0..3 -> $even, $odd {
    say "Even: $even \t Odd: $odd";
}

An appropriate theme song could be "Start of Something Beautiful" by Procupine Tree (which just happened to be playing on RadioParadise twice while reading and then re-reading the link above on alternating even and odd days).

 | Perl | 0 Comments

Going to attend the 7th Dutch Perl Workshop tomorrow in Arnhem.

Cannot wait to get up bright and early for a fun and relaxing day dedicated to the fascinating world of Perl. Last year was a blast and with lots of interesting talks I look forward to the trip.

During the ninety minute drive east, I'm going to crank up my latest Porcupine Tree CD and prepare myself for the busy day of mental gymnastics.

 | Perl | 0 Comments

Sometimes after a long and weary day at work you just do not feel like making any comments.

@no_comments = grep {!/^#/} @blahblahblah;

 | Perl | 0 Comments

So this evening I happened to find out about autodie, thanks to the latest entry in the Modern Perl Books blog by chromatic. Cool stuff.

So I had to run home right away and try it myself, and it works! The following simple snippet:

#!/usr/bin/perl

use strict;
use warnings;

use autodie;
open (my $fh, "<", 'this-file-does-not-exist');
...

generates the following error message:

Can't open 'this-code-does-not-exist' for reading: 'No such file or directory' at x.pl line 8.

No need to waste all that time trying to remember where to stick all those die() statements all over the place (do I use || or do I use or?). So from now on I'll be using autodie just for fun and for work and for play.

Check out Modern::Perl for yourself.

 | Perl | 1 Comment

All those weird Dutch characters were messing me up, and my Perl code was generating all kinds of cryptic errors, like: Malformed UTF-8 character, Wide character in print, etc.

You see, buried deep in the Perl innards somewhere, something was choking bad with such double dotted characters like ë, ö, etc.

I struggled with a number of my own home-grown solutions, but they didn't work well with all possible situations.

Finally in desperation, while perusing through one of my favorite recluses for inspiration, the good old CPAN, I happened to spy the Encode module.

A little bell rang in my head, and I knew I was in the right place. Getting warm, getting warmer, warmer, boiling, boiling hot ... bingo.

$text = Encode::decode('iso-8859-1', $text);

That's the simple and basic little statement that saved me and made my day. What could possibly be easier than that, and why was it so hard for me to find?

Maybe in the future I should visit CPAN more often and earlier, and not think so much of myself. As if I can always solve these grueling problems on my own.

I'm a pretty smart guy, but a little assistance from my Perl friends is always a welcome helping hand.

 | Perl | 2 Comments

Being the hard-core developer type person that I am, every couple of years or so I like to take up a new programming language. This activity provides me with new insights into the wonderful world of programming, seeing how other people tackle interesting problems in different ways.

So last month I picked up a copy of Programming in Lua, and boy has it been a fascinating read. I can definitely recommend purchasing a copy of this book to add to your arsenal of programming literature.

Since my favorite programming language is Perl, each new book I study makes me rethink and compare things about other programming language with Perl (and its potential limitations). This is what I have been doing with Lua.

Two interesting features of Lua which would be great if Perl could do something similar are: "tail-call elimination" and "coroutines".

Tail-call elimination

Basically a tail-call is a goto in disguise. Place as the last statement in a function a return g(x) and you've got a tail-call:

function f(x) return g(x) end

Since the function f(x) has nothing else to do, it doesn't make sense having it wait around until the tail-call returns, using up unused resources like the stack. Might as well avoid using the extra stack space, making it possible to call an unlimited number of nested calls without worrying about the stack overflowing. The following example function can be called forever and the stack will never run out.

function foo(n)
    if n > 0 then return foo(n -1) end
end

A useful example application mentioned in the book, would be traversing a maze with the tail call providing a simple state machine describing going from one cell to the other. Each step goes north, south, east or west into the adjacent room, the exit being the tail-call which transports you from one room to the next.

Coroutines

A coroutine is another wonderful Lua concept. Very similar to threads, it provides a single line of execution within its own context. Several coroutines can work hand in hand, for example in a producer-consumer relationship. You can create, yield and resume coroutines.

Take the example of a producer coroutine reading lines from a file, passing the text to the consumer coroutine. The consumer coroutine receives from the producer.

function consumer (prod)
    while true do
        local x = receive(prod)
        io.write(x, "\n")
    end
end

The send and receive functions provide the gates on each side of the read-write pipe.

function receive (prod)
    local status, value = coroutine.resume(prod)
    return value
end

function send (x)
    coroutine.yield(x)
end

Finally, the producer-coroutine looks like this:

function producer ()
    return coroutine.create(function ()
        while true do
            local x = io.read()
            send(x)
        end
    end)
end

Coroutines can be used for many other things, like iterators or non-preemptive multi-threading applications.

What about Perl?

An interesting challenge could be to see how Perl might be used to implement similar functionalities like those that Lua does natively. As Perl advances and becomes more powerful, it makes sense to see how other programming languages work, and whether or not Perl could be extended to include more advanced concepts.

You'll also want to check out meta-tables and meta-methods, which I believe could be made part of Perl in the not-so distant future.

Official Website

If this all sound confusing, get the book where it's explained clearer and in more detail.

Be sure to check out The Official Lua Website where you will find alot of documentation and tons of examples to whet your curiosity.

 | Perl | 11 Comments

During my lunch break I meandered my way along the canals and through the narrow alleys to the local book-store.

This book-store is pretty big, five floors filled with millions of books. They've got this huge eating area which always smells delicious. My favorite section of course is the computers section (followed by modern literature, and then science, and then psychology).

Several weeks ago, I was there and noticed that there were very few Perl books on the shelves. Only two measly copies of Mastering Regular Expressions and one copy of Learning Perl whose cover had an ugly crease in it.

With a rather disappointed look on my face, I asked the guy how come there were so few Perl books. He shook his head and told me that lately they just weren't that popular. The previous day he had re-ordered some titles, and they'd arrive in about a week or so.

Well there I was three weeks later, and there was not a single Perl book to be found. Just an empty spot becoming ever so cluttered with overflowing JavaScript and ActionScript books which were taking over the section dedicated to Scripts. What a sad day for me.

I believe it is high time to come out with some new titles. If I had more time on my hands maybe I'd try to write a book. There are many talented writers out there and perhaps they are coming up with some creative variations on the subject.

Hopefully with all of the new and exciting Perl-ish happenings on the rise, there will be a new barrage of literature appearing on the shelves some day in the not so distant future.

Until then I'll just have to be patient and scour the Internet looking for interesting tidbits in order to satiate my hunger.

 | Perl | 1 Comment | 0 TrackBacks

The Perl module CGI::Carp allows you to define a different error handler than the boring "A Software Error Occurred" one by using set_message() like this:


use CGI::Carp qw(fatalsToBrowser set_message);
...
set_message(\&handle_error);

Now all calls to die() are caught and sent to the user-defined subroutine handle_error() which will present the user with a nicer HTML page rather than the boring default one generated by CGI::Carp. Pretty nifty.

The only problem with this is when you are debugging. The contents of the HTML page are barfed up and scattered across stdout. This makes it hard to search through all of the HTML and find exactly where the error description, error code and line number is.

So what you need to do is define a simpler user-defined error handler which generates a plain-vanilla printf message.

How can the script detect whether or not it is in the debugger? Simple, just check if &DB::DB is defined. If it is defined, then call set_message() and pass it the simpler error handler like this:


set_message(\&handle_error_printf) if (defined &DB::DB);
...
sub handle_error_printf {
    my $msg = shift;
    print("$msg\n");
}

You're on your way to a happy and productive life as a Perl debugger kind of person.

 | Perl | 3 Comments | 0 TrackBacks

I've been doing alot of bash scripting the last few weeks. Struggling with all kinds of nasty problems and error handling stuff, I have discovered what a powerful utility this bash thing is.

Of course, when it comes to powerful scripting languages there's no substitute for Perl. Sometimes certain problems are a bit too complex for bash and it is nice to be able to fall back on Perl.

Let's say that I have an input file config.tmpl with a single line containing [% base_url %] and I want to generate a configuration file config replacing the value of base_url with $BASE_URL as defined earlier in the bash script, e.g. BASE_URL=http://www.kiffingish.com/utils.

One way of managing this is by using good old sed like this:


cat config.tmpl | sed 's!\[% base_url %\]!'$BASE_URL'!' >config

Sure this is fine and dandy, but what do you do if you have multiple lines in config.tmpl which need to be substituted on the fly? This is where Template Toolkit comes to the rescue.

I've added another line in config.in containing [% index_file %] which needs to be replaced with the value of $INDEX_FILE. A bash one-liner with the help of Template Toolkit works wonders:


perl -MTemplate -e '$t = Template->new(); $t->process('config.tmpl', {base_url => '$BASE_URL', index_file => '$INDEX_FILE'})' > config

If you are bit paranoid, you can extend the above one-liner with some error checking just in case:


perl -MTemplate -e '$t = Template->new() || die "$Template::ERROR\n"; $t->process('config.tmpl',{base_url => '$BASE_URL', index_file => '$INDEX_FILE'}) || die $t->error()' >config

Now if you are like me and even more overcautious. one more sanity check is in order. Always expect the worst, and if this worst happens, make sure that you can trouble-shoot the situation quickly and efficiently.

That's why at the beginning of the bash script, I also double-check that the Template Toolkit module is indeed installed.


# Make sure that the Template Toolkit is installed
perl -MTemplate -e1 &>/dev/null
if [ $? -ne 0 ]
then
    echo Template Toolkit is not installed, please install first.
    exit $?
fi

Isn't the Template Toolkit truly magical? That's why I use it very often to help automate even the most complex chores. Thanks alot Andy.

 | Computers and stuff | 0 Comments | 0 TrackBacks

I'm not about to claim that I'm some kind of expert on the subject, but I think it's fair to say that I've experienced my fair share of ups and downs over the years which makes me a little bit wiser.

Put simply the questions is how do we avoid failure when designing and implementing complex software products?

This is how I would answer that question.

  • The golden rule of thumb to avoid failure is to figure out early what the biggest risks to success are, and then to keep them in mind every single day. Keep this up until success is achieved.
  • Another key to avoiding failure is to admit openly when things start to go wrong, or better yet when you expect that things might go wrong. Don't hide the truth because you are worried that your boss will get angry or that you will lose face with your team members.
  • If things start to go better than expected, then celebrate it and make it publicly known. You guys have struggled really hard and deserve the recognition for work done well. Go out and have a party, but don't get too drunk because it's bright and early as usual the following day.
  • Feel proud of what you are making and treat it like your baby. Protect and cherish it, nurture it and play with it.
  • Admit defeat if needed and just start all over again. It is much better to restart with new insights than it is to plug along with an ugly product which keeps getting uglier, and finally slowly sink into quicksand.
  • Use sound metrics to measure progress and regularly decide where you, where you are headed, and possible obstacles along the way which will delay progress.
  • Learn from your mistakes, write them down, keep this list with you at all times, and reread it at least twice a day.
  • Finally remain open-minded, honest and embrace change, which will happen whether or not you want it to. Change hurts while it is happening, but afterwards it makes you feel a whole lot better.

One could easily say that the statements above apply to developing successful software products as well as to most challenges in life.

 | Perl | 0 Comments | 0 TrackBacks

There's been some talk lately about this new-fangled Apache module called mod_perlite a.k.a. the do-it-all like mod_php but better module for Perl.

Since by nature I am a curious kind of guy looking for yet another interesting challenge, I'm going to have a look at it for myself.

The idea behind mod_perlite is appealing. As a lightweight replacement for mod_perl, mod_perlite is much easier to install, embeds a Perl interpreter in high memory, supports the core CGI functions and has a much smaller memory footprint.

Good old mod_perl is very powerful indeed. I've done alot with it and think it's a fantastic beast. However, it is simply not accessible to the average bloke because it is complex and hard to learn. Have you ever realized how heavy the book Practical mod_perl is with its nearly one thousand pages?! Also, hosting companies are not eager to allow its subscribers to twiddle around with potential dynamite and having to support poor customers sucked down in mod_perl quicksand.

Hey, let's make Perl as easy as PHP for regular users to deploy and for web hosting companies to give as an appealing dynamic web application server stack!

For those masses of kind folks out there who are not computer savvy and not waiting for the headaches of fighting mod_perl, this makes mod_perlite a no-hassle and feasible solution for the low-end plain vanilla servers out there.

Imagine how screaming fast it could be on quad servers hooked up together to provide high performance dependable web solutions.

Perhaps even Lighttpd can come into the picture, why not? Hey now, that's an interesting idea. Writing Lighttpd modules is fairly effortless and hooking this up with Lua could become a real eye-opener.

Wouldn't it be nice to have an one-two-three web server setup that installs easily and just does what it is supposed to do? The blog server market is exploding and could very well benefit from this.

I've got some time on my hands for the next week so I'm going to check mod_perlite out for myself.

 | Perl | 0 Comments | 0 TrackBacks

Came home today to discover a package from Amazon waiting for me on my desk, and when I opened it I was excited to discover that the new Catalyst Book arrived.

I already started reading it, and I plan to devour it fully this weekend between my two golf tournaments.

In the meantime, I've already learned alot about the Catalyst Web Framework through weeks of hands-on experience at work, but I'm sure there's alot more extra stuff to learn by reading this fine book.

I'll be sure and write a (positive) review when I'm done.

 | Perl | 0 Comments | 0 TrackBacks

There were many interesting presentations given at the Sixth Dutch Perl Workshop earlier this year in Arnhem. The event was well organized and many people showed up.

I met many really interesting people there and even had the honor of giving my own presentation in front of the dynamic and fun-loving public. My presentation was called Perl and Scrum. Here's the powerpoint.

In the evening they drank some whiskey and played this weird card game called Fluxx.

 | Perl | 4 Comments | 0 TrackBacks

For years now, I've been using a really great blogging tool called Movable Type Pro. This advanced utility does pretty much everything you'd ever want. Well, most everything that is.

Wouldn't it be great if you could also somehow automatically send out a twitter update (tweet) every time that you've created a new blog entry? Something like this:

Well, as of this very moment you can! All you have to do is keep reading, and if you are patient enough and read carefully what I have to say, then I will reveal to how it's done. Actually it's really quite easy.

Let's call it "blog tweeting".

This is the approach. Whenever a new entry is created, we want to tweet something interesting to the big bad world, grab everyone's attention that something really important has happened. Some kind of catchy phrase would be nice. I use the text "Yet another blog entry" followed by the entry title followed by a url you can click on if interested.

Nowadays, since tweets are deemed short and to the point, rather than use the complete url, which can get quite long, we want to include a shortened version of the url which fits nicely into the short message. The tinyurl service is the popular choice nowadays, so I will use that.

First of all, you need to have a couple CPAN modules installed, namely Net::Twitter and WWW::Shorten::TinyURL. These are installed in the usual way:

# cpan -i Net::Twitter WWW::Shorten::TinyURL

Net::Twitter is based on Moose meaning that the installation will pull in tons of extra dependencies. If you do not want this and only need to tweet an update, then you probably only want to install the lite version:

# cpan -i Net::Twitter::Lite

Alright, let's get started. At the top of your Perl script blog-tweet.pl include the following CPAN modules:

use DBI;
use WWW::Shorten::TinyURL;
use Net::Twitter::Lite;

Now you want to setup the usual database stuff using your movable type username and password like this:

my $dsn = 'DBI:mysql:<database>:<hostname>';
my $db_user_name = '<user_name>';
my $db_password = '<passwd>';
my $dbh = DBI->connect($dsn, $db_user_name, $db_password);
my $url = 'http://www.<domain_name>.com/';

The database query needs to grab the latest blog record from the mt_entry database where it is a blog entry (entry_class = 'entry') and the entry is published for view (entry_status = 2). This is what it should look like:

my $sth = $dbh->prepare(qq{
    select
        entry_title as 'title',
        entry_basename as 'basename',
        entry_created_on as 'created_on'
    from
        mt_entry 
    where
        entry_status = 2
            and
        entry_class = 'entry'
    order by
        entry_created_on desc
    limit 1
});
$sth->execute();
my $rec = $sth->fetchrow_hashref();

The field formats are:

  • created_on - "yyyy-mm-dd hh:mm:ss"
  • basename - "word_word_word"
  • permalink - "blog_root/yyyy/mm/word-word-word.html"
my $basename = $rec->{basename};
$basename =~ s/_/-/g;
my ($year, $month) =
    $rec->{created_on} =~ /(\d\d\d\d)-(\d\d)-.*/;
my $title = $rec->{title};
$url .= "$year/$month/$basename.html";
my $prev_url = '';

Get the previous url, if possible.

if (open(FH, '<blog-tweet.txt')) {
    # File exists.
    $prev_url = <FH>;
    close FH;
}

If new blog entry created, tweet update.

if ($prev_url ne $url) {
    open(FH, '>tweet-my-blog.txt')
        or die "Can't open 'blog-tweet.txt' file: $!";
    print FH $url;
    close FH;

    my $nt = Net::Twitter::Lite->new(
        username => '<username>',
        password => '<passwd>');

    # Convert longurl to shorter tinyurl.
    my $short_url = makeashorterlink($url);
    my $tweet_message =
        "Yet another blog entry '$title' $short_url";

    # Tweet you Update!
    my $result = eval{ $nt->update($tweet_message) };
    
    if ($@) {
        print "Tweet update: $tweet_message, failed ($@)\n";
    }
    else {
        print "Tweet update: $tweet_message, succeeded\n";
    }
}
else {
    print "No new blog entries yet.\n";
}

Finally, don't forget to cleanup.

$sth->finish();
$dbh->disconnect();

The final step is to create a simple cronjob which will run this script every once in awhile. Since I usually write at most one or two entries a day, I've added a cronjob to run once a day at 16.30 in the afternoon:

# crontab -e
30 16 * * * cd /path/to/cgi/scripts && ./blog-tweet.pl

That's pretty much it, have fun blog tweeting!

 | Perl | 5 Comments | 0 TrackBacks

Everywhere you look these days in Perl literature, chances are that you'll come across references to Moose, how great and flexible it is and so forth.

Since I had such a lousy game of golf this afternoon and lost my first matchplay round six down, I needed a way to inspire myself. So what could be better then reading the Moose::Manual this evening?

Boy, was I in for a frustrating surprise.

I hate to admit it, but all this Moose stuff is not easy for me (grumble). Rather than getting all excited and inspired like I hoped, I'm sorry to admit that it's making me feel rather sad that I cannot figure this out.

Am I supposed to be able to understand this Moose stuff? After so many years of getting pleasure in tackling all kinds of complex programming issues, have I simply reached my limit? Time to give up trying to be a Perl guru, jump ship, and be forced to become a golf hacker the rest of my life? What do other fine Perl souls out there think about it?

Here's an example that better illustrates my frustrations. In the Moose::Manual::Concepts one goes on and on about classes, attributes, methods and roles. Not bad. A role has zero or more of this, a role has zero or more of that, a role has zero or more of this and that. Getting more difficult.

Later on one learns that a role is somewhat like mixins or interfaces in other OO languages. Getting more difficult. What the heck is a mixin (and how do you pronounce it)? The good old Wikipedia saves the day with a nice, clear definition:

"In object-oriented programming languages, a mixin is a class that provides a certain functionality to be inherited by a subclass, while not meant for instantiation (the generating of objects of that class). Inheriting from a mixin is not a form of specialization but is rather a means of collecting functionality. A class may inherit most or all of its functionality from one or more mixins through multiple inheritance."

Huh? Nearing apogee and getting impossibly difficult.

Whatever happens, I have promised myself to hang in there. Read and reread as much as I can. Stay smart. Get smarter. Figure it all out or else.

What with so many Perl gurus out there getting all fired up about Moose, mixin and stuff, why I want to join the fun as well!

Tomorrow it's all about Moose::Manual::Classes and then next the world.

Wish me luck.

 | Perl | 3 Comments | 0 TrackBacks

Or perhaps better yet I should rephrase the title above and instead write: Is agile development conducive to Perl?

For the last ten years or so there's been a big rage about the benefits of agile software development and how much better this methodology is compared to good old Waterfall or RUP or Ruby on Rails or whatever.

I would like to claim that Perl is just as good if not better than any other programming language when it comes to going agile. I've used it often enough and it has resulted in successful products hitting deadlines and bringing in big bucks. Who ever told us that early-to-market is an impossible task?

Perhaps Perl is not ideal, but it's flexible enough. Perl fosters creativity in such a way as to bring about visible results very quickly. There are many ways of doing things, and these alternative can be compared, the good with the not so good and even the bad with the outright bad, when choosing the most viable direction to take. Perl means moving forward not backwards.

Is speed the most important? Sure. Should we keep quality in mind? Yes, of course. Is there enough time to test? You better or else. Should we demo even though it's not quite ready. Yes and yes.

Let's have a look at Scrum which is one way of being agile. Since I've had more experience there, I feel more comfortable discussing it in light of the Perl programming language.

Scrum's success is based on a number of important concepts including the following:

  • Describe requirements as user stories
  • Prioritize tasks by business value
  • Commit to short-term goals and go for it
  • Allow the team to do anything to accomplish the goal
  • Do not disturb development during each cycle
  • Develop quickly and pragmatically

  • Take part in daily stand-up meetings
  • Measure speed by iterative development cycles
  • Empower the development team to make any and all decisions
  • Embrace change because it will happen
  • Review and improve
  • Foster bleeding-edge technology that might break things
  • Accept delays as part of life and make them public
  • Tackle risks early and do not fear failure
  • Verify, rework and move forward
  • Be proud of what you create
  • Have a fun and relaxing time getting things done

I could go on and on explaining the fine art of doing Scrum within the wonderful world of Perl, but I believe I've said enough for the time being.

Hopefully my short discussion here has tickled enough people out there to make them think and reflect upon their own experiences. Enough so at least that they are inspired to leave comments of all kinds, foster even more discussion, defending and/or judging good old Perl as a agile way of doing things (or not).

So is Perl really conducive to agile development? I think so.

 | Perl | 4 Comments | 0 TrackBacks

Recently I've been setting up an extensive test harness suite for a web-based application running on the Catalyst Web Framework for Perl.

In addition to the popular Test::MoreCPAN module, many of the tests make use of the CPAN module Test::WWW::Mechanize::Catalyst where I run automated scripts to access various pages, fill in fields with various values, submit forms and check for success or failure.

One of the tests involves creating a new user account that generates a notification email which is sent to the new user. Within the message text there is a verification link. The idea is that upon receiving this email, the user will click on this link and be redirected back to the application to a welcome page. This welcome page verifies that registration has been completed successfully. The user is invited to login in by submitting a form with the username and password pre-filled.

The problem is that I do not want to be generating all kinds of external emails into the big bad world for these tests. Besides, how can I use automated scripts when they depend on external events like users having to click on links in emails wherever they might be?

So here's the trick. First of all I redefine the Email::Send::send() method so that I can hook into it thereby mocking it's behavior. This redefined method is used to scrape out the embedded validation link we must click on in order to finish the registration process.

our $email_mime_ref;
{
    no warnings qw/once redefine/;
    *Email::Send::send = sub {
        my ($self, $message, @args) = @_;
        $main::email_mime_ref = $message; return 1; };
}

Note that we use no warnings qw/once redefine/ in order to disable the warning messages for redefining the method and only using it once.

Whenever Email::Send::send() is called, we copy the message for later use. Note that since we are in the namespace of Email::Send when this is called, we need to make sure that the message is copied back into the namespace of where we are calling from, namely $main::*:

$main::email_mime_ref = $message;

Later on in the test suite it is time to submit the form like this:

$mech->submit_form(
    form_number => 0,
    fields => $fields,
    button => 'submit' );

Now scan through the message text and extract the uri, there should only be one present. I'm using the CPAN module URI::Find to simplify life.

my @uris;
my $finder = URI::Find->new( sub { push @uris, shift; } );
$finder->find(\$email_mime_ref->body_raw);

As a sanity check (you never know) I check that indeed only one link is present in the message text:

is(@uris, 1, "Found only one URI '$uris[0]' in email message");

Finally, we simulate clicking on this link which should bring us back to the welcome page:

$mech->get_ok($uris[0], "Click on URI '$uris[0]'");
$mech->content_contains("Welcome " . lc($username) . 
    ", your email has been validated. Please log in.");

We did it, so let's pat ourselves on the shoulders and call it a night.

 | Perl | 0 Comments
Here's a review I wrote about the book 'Perl Testing: A Developer's Notebook' by Ian Langworth & chromatic.

"Excellent overview and introduction to the art of testing Perl programs. This modestly-sized book covers a wide range of types of testing from the very simple Perl script to the more advanced web application. It's not only about writing tests but managing them as well and then making sure that your code can be distributed in a useful manner. I especially found the chapter about testing untestable code very insightful, where the use of mocking modules and mocking objects is essential. Have you ever needed to override live code by hacking deeply into their packages? Well, this book will help you out with this delicate matter and make you more confident with testing, testing and testing. Most people have an aversion to testing, but here you can get quickly up to speed and even enjoy the fine are of testing. There are many references to other CPAN modules which is useful to know about. Of course, any book authored by chromatic has to be worth the read."

O'Reilly books
 | Perl | 2 Comments

Ever wondered how to quickly convert an array to a hash on the fly? Well here's one way to do it:

my %h = map { $_ => 1 } qw/one two three four/;

Feel free to come up with other perhaps more efficient and/or elegant and/or cryptic ways of doing this.

 | Perl | 0 Comments

Thought I was being real clever by trying the following last act of pure desperation:

$SIG{__DIE__} = sub { print "Please don't let me die!\n"; };

Unfortunately those were my last gasping words before I was aborted and sent to who knows where.

 | Perl | 0 Comments

Screenshot-Padre 0.35.png

Padre - Perl Application Development and Refactoring Environment

Special thanks goes to Gabor Szabo for helping me out.

If like me you use Ubuntu, don't forget to read the download instructions very carefully and do the following:

$ apt-get install libwxgtk2.8-0 libwxgtk2.8-dev libwxbase2.8-dev libwxbase2.8-0

$ apt-get install libmodule-build-perl libextutils-cbuilder-perl libmodule-pluggable-perl g++

Optionally, which was the case for me, you might also have to run:

$ sudo cpan -i Wx Alien::wxWidgets Padre

Then sit back, fire it up and enjoy:

$ padre

 | Perl | 3 Comments

After hearing the good news Padre 0.34 released I've been giving it a go but with little success.

Despite claims on the download page, I've been struggling now for two whole evenings with very little luck.

$ sudo cpan -i Padre

Looks pretty innocent and straight forward doesn't it? Yeah right. A bit of a nightmare, which is really too bad. I was really excited to try it out and get involved myself.

You might also like to read Padre + Catalyst. See also Padre, the Perl IDE.

 | Perl | 6 Comments

Let's say that you need to check the validity of some input value. If it is found in a list of acceptable values then you continue otherwise you need to croak some error message.

For starters let's assume that the list of acceptable values is contained in the following array:

my @list = qw(email name telephone address);

Also don't forget that in order to be able to croak you need to include use Carp; in the file.

Here's the most straight forward way to do it:


sub func
{
    my $value = shift;
    my $found = 0;
    for my $next (@list)
    {
        if ($next eq $value)
        {
            $found++;
            last;
        }
    }
    croak "Invalid value '$value'" unless $found;
    ...
}

Here's another especially clever albeit slightly cryptic way to do it[1]:


sub func
{
    my $value = shift;
    { map { $_ => 1 } @list }->{$value}
        or croak "Invalid value '$value'";
    ...
}

Finally, if you are familiar with the List::MoreUtils module, then here's yet another way to do it:


use List::MoreUtils qw/any/;

sub func
{
    my $value = shift;
    croak "Invalid value '$value'";
        unless any { $value eq  $_ } @list
    ...
}

As you can see there are many correct ways to do it and probably many more.

[1] Perl Medic p. 122

 | Perl | 2 Comments
About ten days ago, I ordered the book 'Perl Debugged' and I was pretty excited when the package arrived today, falling gently from the mail slot in the door and landing upside sown on the hallway mat.

At first I was a little surprised how thin it seemed, but still full of anticipation, I ripped the package open and yanked out the book.

It turned out to be a copy of 'Mijne erste Trompetenshule' some German music book for kids learning how to play the trumpet.

When you think about more closely, it makes sense that Perl and trumpet playing have alot more in common that you realize.

What a letdown, but kind of funny and ironic at the same time.
 | Perl | 0 Comments

Here's an easy one-liner which will automatically update all of the CPAN modules installed on your machine:

$ sudo perl -MCPAN -e 'CPAN::Shell->notest(install => CPAN::Shell->r)'

I always do it with sudo but you might not have to depending on your preferences.

Since waiting around for all of the tests to complete can be quite dull, I use notest() which might be considered risky by others.

 | Perl | 0 Comments

By far the most efficient way to do a global in line replacement on an array is by using the following substitution one liner:

s/apples/oranges/ for @entries;

Why go through all of the trouble of using a for loop when you can impress your family and friends by doing it so much more elegantly?

 | Perl | 0 Comments
The Enlightened Perl Organisation is sponsoring the Perl Iron Man Blogging Challenge.

So get off your lazy butts and start blogging now!
 | Perl | 2 Comments

Often out of curiosity, and perhaps due to an acute case of extreme boredom, I like to see what is going on behind the scene, e.g. within the deepest internals of good old perl.

Take for example the number and type of perl modules being loaded from a single use statement.

Since I've been playing alot with Moose lately, I'll use that as an example.

Roll up sleeves, cross your finger and fire up a terminal session and enter the following command:

$ perl -e 'use Moose; print join("\n", sort keys %INC)'

Lo and behold you will see a list of seventy-seven or some appear before your eyes:


Moose does not export its sugar to the 'main' package.
AutoLoader.pm
B.pm
Carp.pm
Carp/Heavy.pm
Class/MOP.pm
Class/MOP/Attribute.pm
...
overload.pm
re.pm
strict.pm
vars.pm
warnings.pm
warnings/register.pm

If you try Catalyst instead of Moose, the list will be even longer (169).

So what am I trying to prove? Not much I guess except for the fact that perl allows you to acquire much interesting insight with it's wonderful world of one-liners.

(What does the very first line 'Moose does not export its sugar to the 'main' package.' really mean?)

See Perl Medic by Peter J. Scott for an excellent read.

 | Perl | 0 Comments
Since Perl is my favorite programming language, I've collected quite a number of books about Perl in the last few years.

Perl_books.jpg
The Perl section of my personal library.
 | Perl | 0 Comments
Parsing is the action of splitting up a data set into smaller, more meaningful units in order to uncover some form of meaningful structure from a sequence of these units.

Parse::Lex
Pro Perl Parsing
 | Perl | 0 Comments

For many many months now, the random link at the top of this page just below the banner hasn't been working. I decided to fix it once and for all.

First of all I redefined the link to refer to a new CGI script mt_random.pl which I wrote myself using good old Perl. Here is how the new link is defined:

<a href="/cgi-bin/mt_random.pl?blog_id=1" title="Jump to a completely random place on this blog...">Random</a>

Of course the whole random magic of the situation is the Perl script mt_random.pl itself, which looks like this:

#!/usr/bin/perl -w
use DBI;
use CGI;
use strict;

my $q = new CGI;

my $format_url = "http://www.kiffinsblog.com/archives/%d/%0.2d/%s.html";

my $hostname = 'localhost';
my $database_name = 'db_name';
my $user = 'db_usr';
my $password = 'db_password';

my $dsn = "dbi:mysql:database=$database_name;host=$hostname";

my $blog_id = $q->param('blog_id') || 1;

my $dbh = DBI->connect($dsn, $user, $password) or die "Can't connect to $dsn: $DBI::errstr";

my $sql = <<EOF;
SELECT
  entry_basename,
  entry_title,
  date_format( entry_created_on, '%Y' ) AS entry_year,
  date_format( entry_created_on, '%m' ) AS entry_month
FROM
  mt_entry,
  mt_author
WHERE
  entry_blog_id = $blog_id
AND
  entry_status = 2
AND
  author_id = entry_author_id
ORDER BY rand( )
LIMIT 1
EOF

my $sth = $dbh->prepare($sql);
$sth->execute();

my $ref = $sth->fetchrow_hashref;

print $q->redirect(sprintf($format_url, $ref->{entry_year}, $ref->{entry_month}, $ref->{entry_basename}));

You can now try it out yourself by clicking on the link above, and if you cannot find it then clicking here.

Pretty amazingly magical don't you think?

 | Perl | 0 Comments | 0 TrackBacks
$_=1234567.7891;
s/\B(?=(...)*\.)/ /g;
print;
 | Perl | 2 Comments | 0 TrackBacks

How to distinguish comment and/or email spam from the real thing:

#!/usr/bin/perl
use strict;
use CGI qw( :standard );
my $server_name = server_name();
my $referer = referer();
my $is_spam = $referer !~ /$server_name/;
 | Perl | 0 Comments | 0 TrackBacks

Hey, did you know that there was a Javascript extension to the Template-Toolkit?

That's exactly what Jemplate does, and it does it quite elegantly I must admit.

This CPAN module is definately worth looking into, just for fun at least. For more information you might want to check out the article Jemplate - A Template Toolkit for Javascript.

Closer inspection of the code reveals that this is nothing more than a quick switch Template::Directive sleight of hand, that's all really.

You might also want to consider using OpenThought - Web Application Environment which doesn't require page reloads.

Not so sure if I will ever use it, but it is interesting to know about anyway.

 | Perl | 0 Comments | 0 TrackBacks

Unlike the special constructs which make creating references to anonymous hashes and arrays as easy as pie, there is unfortunately no easy-and-quick way in Perl to create so-called nameless scalars. Kind of a bummer.

Can this be viewed as a serious shortcoming of Perl? Could be or not.

Well there is still hope. Instead you will have to do something like the following:

my $scalar_ref = \do{ my $anon_scalar = 'what the heck' };

Now it is up to us Perl folks to figure out what this actaully means and how one should go about using it effectively (or not).

Borrowed from one of my favorite Perl books which is called 'Perl Best Practices' by Damian Conway.

 | Perl | 4 Comments | 0 TrackBacks

This is a truly amazing discovery for me.

As it turns out, it is possible to debug Perl threads, forked processes as well as CGI programs. You can even debug modules which have been preloaded, inspect object-oriented Perl stuff and even verify user-defined regular expressions on the fly.

Just to think of all those late night debugging episodes doing it my boring way when I could have saved hours and hours (if not days) by doing it the right Perl way.

To think that I was so naive as to believe I knew most there was to know about Perl.

This fine book (Pro Perl Debugging) has turned out to be a real eye-opener for me.

While not for the light-hearted, any true Perl person worth his or her weight in salt will definitely have to read this book, which I recommend highly.

 | Perl | 4 Comments | 0 TrackBacks

Yesterday evening I attended the Amsterdam Perl Mongers meeting for the very first time.

I was the only one without a laptop, so I had to sit patiently at the table twiddling my thumbs while the gang discussed those perl things we all love and cherish.

This computer language called Perl is quite unique when it can inspire so many folks to come together and talk about it once a month.

Next month I will be sure to bring my laptop with me so that I can melt better into the group. Can't wait.

 | Perl | 6 Comments | 0 TrackBacks

Speaking of elegant ways to get something complicated done with a minimum amount of good-old perling, here's an interesting algorithm:

sub random_string
{
  my $max = shift;
  return join '', map { ('a'...'z', '0'...'9', 'A'..'Z', '0'...'9')[rand 72] } (1..$max);
}

In case you couldn't figure it out yourself, it takes a single integer as input and generates a string of that many characters made up of random upper- and lowercase letters and digits.

 | Perl | 1 Comment | 0 TrackBacks

An elegant way to mix and match hash entries is by using the technique of hash slices. For example, let's just say that you have defined the following hash:

my $config = {
  firstname => 'Joseph',
  lastname => 'Smith',
  user => 'pickle',
  ...
  database => 'fruits',
  password => 'z4KLf3&3z',
  ...
  host => 'zeta.demon.nl',
};

Suppose that you are only interested in the hash-keys related to the database stuff. Then you can use the following fancy one-liner:

my ($dbhost, $dbdatabase, $dbuser, $dbpassword) =
  @$config{ qw( host database user password ) };

As the saying goes, there is always more than one way to do it with Perl. Pretty neat stuff, wouldn't you say?

 | Perl | 0 Comments | 0 TrackBacks

For the third time now in less than a year, I am rereading that fantastic Perl Template Toolkit book.

Not only is this a great read and each time around I discover new and interesting tidbits I had missed before, the framework allow a robust plugin design allowing one easily to extend the tool in advanced ways.

Here it is in a nutshell

  • Define the framework from the requirements
  • Place the front-end on top of this
  • Implement the processing between elements
  • Define the underlying interface to drive these processes
  • Snap in the various plugins to achieve this
  • Test it all based on the original requirements

For more information about this great tool, you might want to check out the official template toolkit website.

Have fun.

 | Perl | 0 Comments | 0 TrackBacks

Hey Geo::Coder::US is here, and you can even use the native SOAP extension if you want to be really cool.

Build Your Own Geocoding Solution with Geo::Coder::US.

 | Perl | 0 Comments | 0 TrackBacks

The postman came by again and brought me two more books that I ordered some time ago:

  • Perl & XML
  • Programming Web Services with Perl

Thanks alot Amazon.co.uk!

 | Perl | 5 Comments | 0 TrackBacks

Is there anyone out there who can tell me what the following piece of code actually does?

@list_out = keys %{ {map {$_=>1} @list_in} };

If so then please leave a comment if you dare. I am willing to bet a good many euros that not a single person out there knows the answer to this abstract perlishness.

Reference

 | Perl | 0 Comments | 0 TrackBacks

This is more than likely the best way to read an entire file into a given variable $code all in one go:

my $code = do { local $/; <$fh> };

Notice that by localizing the input record separator $/ variable within the brackets, unwanted side-effects are avoided.

Of course, if one is more prone to power slurping, then the module Perl6::Slurp offers a much more advanced interface, but one will just have to be patient and wait awhile.

 | Perl | 0 Comments | 0 TrackBacks

"Then again, almost every maintainability issue is, by itself, marginal. It's only collectively that subtleties, clevernesses, and esoterica begin to sabotage comprehensibility. And it's only collectively that obviousness, straightforwardness, and conformity to standards can help to enhance it. Every samll choice when coding contributes in one direction or the other."

Taken from Perl Best Practices, Damian Conway (p. 165).

In otherwords, when it comes to good old down-to-earth programming, let's not be too clever and just stick to the point. The well-defined point that is.

 | Perl | 0 Comments | 0 TrackBacks

Here's an interesting and very efficient way to transform each list element, returning the list of those modified copies:

my @nice_words =
    apply { s/$EXPLETIVE/[DELETED]/gxms } @words;

That is of course if you are willing to use the not-so well known List::MoreUtils CPAN module.

Give it a go.

 | Perl | 0 Comments

All of a sudden my browser froze up and nothing happened anymore. As it turns out, I had unknowingly introduced a nasty bug into the fancy web application I was working on. This resulted in the dreaded 'deep recursion' error which can be triggered to raise its ugly head by something as innocent looking as this:

sub show_bugs (
    my $recurse = shift;
    # do something
    show_bugs(1) if !$recurse;
}

As you can see here, it is important that one NOT forget the !$recurse or it's dooms day all over again. Be careful, it's a dangerous and unpredictable world out there.

 | Perl | 0 Comments

This MediaWiki thing could be the way to go when it comes to communicating in a pseudo-structured endless manner. You might want to have a look at the Wikipedia (an open-content encyclopedia in many languages), Wiktionary (a collaborative project to produce a free multilingual dictionary in every language) or Wikiquote (a free online compendium of quotations in every language) and more for a quick(?) glimpse into the endless possibilities of this intertwined medium. Pretty amazing stuff, that's for sure.

 | Perl | 0 Comments

"In the end, it is the developers themselves who hold the project together. Each individual bears their own share of the responsibility for finding a task that suits their skills, coordinating with others to keep duplicated effort minimal, and making sure the job gets done."

- Perl 6 Essentials, Chapter 1.

 | Perl | 0 Comments

For true-blue Perl geeks like myself, the Perl Monks web site is an interesting place which is really worth a regular visit. They have this section called Obfuscated code in which you can discover amazing little jewel snippets. Like this one, for example:


#!/usr/bin/perl
*AUTOLOAD = *_;
sub _ { /:+/; $, .= "$' " }
print Hacker(Perl(another(&Just)));

So what does it do? How does it work? What does it mean?

You now have two choices: 1/ Take the challenge, figure it out yourself, and verify you have the correct answer by clicking the button below, or 2/ Be impatient, immoral, and outcasted from the Perl community by hitting the answer button without raising a pinkie.

 | Perl | 0 Comments

Okay so I have got the main parent process up and running just fine. Now it is time to fork off the child processes, opening up the two-way pipes so that they can all communicate with each other. The only problem now is the synchronization which still has a number of slight wrinkles that require a good dose of ironing out. Sometimes it works just fine, but during unpredictable moments it clogs up, resulting in processes freezing, reading/writing becoming blocked, and the whole gateway hanging in thin air. Time to roll up my sleeves and look deeper, much deeper that is.

 | Perl | 0 Comments

So I thought that this weekend I could delve somewhat into the fine art of object-oriented Perl, create my own fancy objects and all. But I keep getting the following aggravating error:

"Can't call method "_init" on unblessed reference at Logger.pm line 8."

What the heck does that mean?

 | Perl | 1 Comment

I am now a full-fledged Perl programmer with a real life assignment about which I feel happy and relieved. Looks like alot of fun as well as a challenging project during which I can hone my programming skills in Perl even more and hopefully impress folks with my abilities so that they will either want to keep me on or decide to put me on another relevent assignment. Thanks alot Perl for making my life that much better.

 | Blogs etc. | 0 Comments

Just for the heck of it, I decided to stick a so-called random button on this blog to give folks a chance to jump around this blog in a more precarious and unexpected way.

If you look closely, you will see the bluish button on the right margin, and placed randomly (note the meta pun) all over the place. The button looks like this:

So how does it work? you might be wondering. Well for those Perl gurus out there it is nothing more than a simple script which scans a given directory, grabs a random HTML-file from the listing and does a good old redirect via the HTTP-header.

Of course, in order for this little code snippet to work, you have to have CGI enabled on your web server, e.g. included as part of your subscription.

Confused? Then here is a little code which I hope helps you folks out:

#!/usr/bin/perl -w
#
#  rand_redirect.pl
#
# Redirect for MovableType where a user will be sent
# to a random blog entry, category or whatever the
# HTML-file is present in the archive directory.
#
use strict;

my $dir = "archives";
my $rootdir = "/Blogger";

use CGI;

my $q = new CGI;

if (opendir(DX, $dir))
{
  my @allfiles = sort grep { $_ ne '.' and $_ ne '..'
      and ($_ =~ /\.html$/i) } readdir DX;
  closedir DX;
  my $num = (@allfiles);
  if ($num > 0)
  {
    my $n = rand($num);
    my $fname = $allfiles[$n];
    print $q->redirect("$rootdir/$dir/$fname");
  }
}

The last step is the easiest. Decide where on the page you want the button to appear, and just add the following code there:

<input type="button" value="Random"
  onclick="document.location='/cgi-bin/rand_redirect.pl'">

Hope this little code snippet helps someone out there whenever and however that may ever be. Please tell me what you think.

 | Blogs etc. | 1 Comment

Now if you click on the random image up on the top left-hand corner of this web page, you will be shown a list of the images directory.

I found this little jewel of a Perl script via the CGI Resource Newsletter which advertised the free script called WebImageLister.

Give it a try and find out for yourself.

 | Computers and stuff | 2 Comments

Here's a little Perl snippet which will place commas in any number string right where they belong:

sub commify
{
    my $text = reverse $_[0];
    $text =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
    return scalar reverse $text;
}

So for example, by calling commify("13245766") the value "13,245,766" will be returned.

All the little commas right exactly at the correct positions using a simple regular expression. Pretty amazing language that Perl is. Does it make sense?

 | Internet | 2 Comments
Alright so I admit it, I have been a naughty boy lately. Desperate to find customers, one often resorts to conniving means, seedy methods bordering on the immoral. Oh well.

You see, I figured why pay one of those companies out there on the Internet tons of bucks for email address lists, or pay them even more to broadcast mailings all over the world when I can do that myself.

I am a pretty smart guy, sometimes. At least that is what I fool myself into believing.

So this is what I did. I wrote a subscription mailing list at GishTeq which allows potential customers to sign up for mailings and newsletters. Later, one may even modify personal settings or opt-out altogether by unsubscribing.

Now the trick is getting people to sign up. Why don't I scan the Internet, collect emails and sign them up myself? When they get the first mailings, they can always unsubscribe.

I created another Perl script which can scan certain sites and scrape off the emails. If possible, it can even log in to subscriber lists and automatically scan these web pages also.

All I do is give the script a site url, start it up and there it goes. Ten minutes later or so I've got my list formatted as CSV so that I can even import it into an Excel sheet for future reference.

You probably won't believe me either if I tell you that with this technique I have successfully harvested more than one thousand warm leads.

Here's a hint (if you know Perl). Use the use LWP::UserAgent module to get the contents of the page and then scan it. See anything interesting, scan deeper via the internal links. Poke around and see if you can find anything interesting. Is there a user id that is passed around? Try all values of that user id from say 1 to 1000 and collect the results.



Sorry, I've been a bad boy. But I want to become famous also.
 | Web Design | 3 Comments
Here's something clever I thought up the other day and decided to use on my new GishTeq website to spruce things up some.

What it does is generate a bulleted list of all the web pages as links in alphabetical order according to the title. Just add the EXEC-include (SSI) statement wherever and load it up for the surprise.



An example of it in action can be seen at the GishTeq sitemap page. Hope you like it. Feel free to use it as you see fit.

 | Web Design | 2 Comments
In case you haven't noticed it yet, I have added yet another new and exciting feature to my weblog. You see, along with the hundreds of other things I am trying to learn these days, Perl is one of the more difficult. Wouldn't it be nice if I could generate a random image? I am certain that everyone reading this entry would certainly agree that such added functionality would improve the quality of this site immensely. Perhaps attracting even more droves of visitors. So that is what I did. In order to see it, just look up at the upper left hand corner of this page and you should see it. Each time you visit or hit the refresh button, the image of the future famous blogger will change.

Here is the script for all you fine folks out there who know a little bit about the wonderful world of Perl programming:



In order to use this, your web host will need to support SSI and the Perl mod Image:: needs to be installed. Feel free to use this at your own risk and good luck.

 | Kiffin Rockwell | 2 Comments

Since my birthday is coming up soon, I decided to order two more books from Amazon in the hopes that my shipment will arrive in time for the big event. They've got less than nine days, but so far I have never had to wait more than a week. Now I will tell you which two books I ordered if you promise not to make fun of me. The titles are:

  • The Java Programming Language by Ken Arnold et al.
  • Effective Java by Josh Bloch.

I figured that I have pretty much learned enough about HTML, Javascript, XML, CSS, Perl and CGI that it is time to take the next jump into the most obvious domain about which I need (would like) to be more knowledgeable. I have heard so much about the wonderful world of Java and at the same time know so very little about it. Time to expand my knowledge another slight click. Is this a sign of getting senile, crazy, too old for this stuff or am I simply a born techie guru type at heart? Take your pick. Any way, the books will add a pleasant counterweight to whatever it is I am planning to do in the not so near future.

 | Technical stuff | 2 Comments

So I thought I would get fancy again and make my guestbook even nicer, nicer than it was ever meant to be. However, after I had changed some of the perl stuff and uploaded it to my cgi-bin directory again it all went boom. That is if I tried to add a new entry to the guestbook and hit the good old submit button, an ugly 500 internal error flew back in my face. Ugh and oops and what? What was the problem exactly? The most obvious choice is to recheck the Perl script for possible syntax errors, but that was perfectly fine. I had only changed a few items (5), and they all looked perfectly healthy to me. When I stuck back the original cgi-script to the server, everything was okay again. Weird. Why did I have to go off and change things, try to make them better but make them worse in the end? As it turned out, the cause of my problems was this and has to do with me "trying" to transfer my development environment to my new machine. The usual hassle. I use the wonderful tool called LeechFTP (sometimes crashes and/or generates cryptic error messages in German but in general pretty dependable and I am used to it). There is this option for setting file extensions which should be automatically uploaded in ASCII-mode. Well, you guessed it. The list of extensions was reset to the default after installation (".txt.htm.html.nfo.diz") and does NOT include the CGI extension. Oops, that means that when I try to transfer the file guest.cgi to my site, it gets sent in BINAIRY mode which is bad. Bad boy. Bummer man. I now quickly fixed that by appending the text ".pl.cgi.htaccess.pm.cfg.cgi" to the end of the default list. Don't want to forget the other types of files I upload regularly and end up having the very same frustrating problem now do I? Now everything works just fine again. Again and again. No use wasting energy doing low-level debugging stuff when that is not necessary. First think, think deeply, before proceeeding to the next step. Again and again.

 | Books | 6 Comments

Right now I am reading a bunch of books simultaneously in my never-ending attempt to acquire infinite knowledge. Nine books all in a row, to be more precise. Depending on my mood at a given instant, I will jump from the one book to the other. Sometimes smack dab in the middle of a chapter, I will close the book I am currently reading and open up another book. Some reading sessions consist of switching books five or six times an hour. I suffer from an insecure feeling that perhaps I am not increasing my knowledge as productively as I should. That what I am reading at the moment is not valuable enough in the sense that I am suffering an acute shortage by not improving my life sufficiently and quickly enough! This can be very frustrating. The innocent pleasures of reading suffer in that regard which is ironic to say the least. There is this endless source of interesting information out there, and there is absolutely no way I can absorb it all in the limited span of my lifetime. By nature I have an addictive tendency, a proclivity which bends me in fixations. Especially when it is in any way remotely related to the esoteric acquisition of knowledge. So why bother in the first place? Infinite knowledge is preferable, of course. Unfortunately one cannot attain this by reading, even if one could have enough time to read every single book in every possible language that has ever been written in the history of civilization. In order to give my readers a hint of how far along this reading adventure I have come, here is a list of books that currently lie on the reading table next to my bedside. The order is from bottom to top, or since I am by nature symetrical and neat, from the widest (usually the thickest, but now always) in decreasing order:

  • Programming Perl, Third Edition by Larry Wall et al.
  • Javascript, The Definitive Guide by David Flanagan.
  • The 7 Habits of Highly Effective People by Stephen R. Covey.
  • Essential CSS & DHTML for Web Professionals by Dan Livingston.
  • Web Design in a Nutshell by Jennifer Niederst.
  • Cascading Style Sheets 2.0 Programmer's Reference by Eric A. Meyer.
  • A Beautiful Mind by Sylvia Nasar.
  • The Power of Now by Eckhart Tolle.
  • Caesar by Colleen McCullough.

As you can see from the list I am pretty much obsessed with Web-related stuff at the moment. However, I try my best to balance this with other non-Web stuff. Reading one book at a time would probably be much more efficient, but I am too impatient. For the sake of simplicity, let's just say that I am about half-way along the pursuit of infinite knowledge.

Recent Assets

  • Keizersgracht.jpg
  • Hole-17.jpg
  • brandnetels.jpg
  • view-hotel-balcony.jpg
  • near-balestrand-sognefjord.jpg
  • roughlong.gif
  • HB3-champs.png
  • chip-shot.jpg
  • rotterdam_blitz2.jpg
  • Rotterdam_blitz.jpg
  • edgerton_golf_swing.jpg
  • webcam-rightside-up.jpg

Recent Comments

OpenID accepted here Learn more about OpenID

Information

This personal weblog was started way back on July 21, 2001 which means that it is 7-21-2001 old.

So far this blog contains no less than 1840 entries and as many as 1827 comments.

I graduated from Stanford 6-5-1979 ago.

I first met Thea 6-14-1980 ago.

Believe it or not but I am 10-11-1957 young.