Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

wickline (135)

  (email not shown publicly)

Journal of wickline (135)

Wednesday July 14, 2004
07:12 PM

thanks pudge!

I just realized today that the 'light' mode was back. Not sure how long it's been back, but I'm glad it has returned.

Thanks! :)


Monday February 16, 2004
10:42 PM

When you think of spam...

...think of me!

I learned today that when users ask google how to get spam, I'm the first name that comes to mind.

A prof was looking into sources of spam on behalf of a student who was developing antispam software and dropped me an email after running that query.

I've also been google's favorite for "colorblind" for quite a while, which brings to mind the following idle trivia: It seems that tens of thousands of users have decided that the best way to get around their local webblocking software is to view porn through the colorblind web page filter. ...yet another reason to hate webblocking software...


P.S.: ...and for the sake of completness, I was google's favorite for "employment objective" back when I was still looking for work, but lost the honor (I think) due to not having updated the page in months.

P.P.S: to avoid spam, I now prefer to send mail from addresses which have the form where foo/bar/baz tend to identify the specific contact/occasion, and is my domain. Address-harvesting bots (so far) ignore list-subscribe addresses, but if they ever spam them, I'll be able to kill the specific address without invalidating other addresses. The 'list-subscribe' technique has allowed me to go without killing any of my ad-hoc addresses for about a year now.

Tuesday July 08, 2003
10:52 PM

re-inventing the pageset wheel

Matts asked about page set code, and decided that my reply was sufficiently compressible that it probably wasn't meaninfull content... so I'm posting it here to see if I'm allowed to put meaningless things in my own journal ;)


=item C<prepare_resultset_paging>( I<$set_size>, I<$page_size>, I<$curr_page>, I<$url> )
Given the size of a current result set (number of hits), the size of our result
pages (ie: showing a list of ten hits per page), and the number of our current
page (zero indexed: ie 0 for the first page in the result set), and the initial
URL (to which the zero-indexed page numbers will be appeneded)... Returns HTML for
links allowing the user to page through the result set. The links will include
a 'previous' and 'next' link where applicable, and will include links to jump
to up to eight other result pages by page number. Generally, the script will
prefer to show four pages before and four after, but for pages near either end
of the result set, that view may be shifted to continue showing eight other
For a general idea, here's a textual representation of different output for
all of the pages in a twenty-page result set (_underlined_ items are links
and whitespace is only added to hilight patterns in the output)
             _next_ page[      1   _2_  _3_  _4_  _5_  _6_  _7_  _8_  _9..._ ]
    _prev_ , _next_ page[     _1_   2   _3_  _4_  _5_  _6_  _7_  _8_  _9..._ ]
    _prev_ , _next_ page[     _1_  _2_   3   _4_  _5_  _6_  _7_  _8_  _9..._ ]
    _prev_ , _next_ page[     _1_  _2_  _3_   4   _5_  _6_  _7_  _8_  _9..._ ]
    _prev_ , _next_ page[     _1_  _2_  _3_  _4_   5   _6_  _7_  _8_  _9..._ ]
    _prev_ , _next_ page[  _...2_  _3_  _4_  _5_   6   _7_  _8_  _9_ _10..._ ]
    _prev_ , _next_ page[  _...3_  _4_  _5_  _6_   7   _8_  _9_ _10_ _11..._ ]
    _prev_ , _next_ page[  _...4_  _5_  _6_  _7_   8   _9_ _10_ _11_ _12..._ ]
    _prev_ , _next_ page[  _...5_  _6_  _7_  _8_   9  _10_ _11_ _12_ _13..._ ]
    _prev_ , _next_ page[  _...6_  _7_  _8_  _9_  10  _11_ _12_ _13_ _14..._ ]
    _prev_ , _next_ page[  _...7_  _8_  _9_ _10_  11  _12_ _13_ _14_ _15..._ ]
    _prev_ , _next_ page[  _...8_  _9_ _10_ _11_  12  _13_ _14_ _15_ _16..._ ]
    _prev_ , _next_ page[  _...9_ _10_ _11_ _12_  13  _14_ _15_ _16_ _17..._ ]
    _prev_ , _next_ page[ _...10_ _11_ _12_ _13_  14  _15_ _16_ _17_ _18..._ ]
    _prev_ , _next_ page[ _...11_ _12_ _13_ _14_  15  _16_ _17_ _18_ _19..._ ]
    _prev_ , _next_ page[ _...12_ _13_ _14_ _15_  16  _17_ _18_ _19_ _20_    ]
    _prev_ , _next_ page[ _...12_ _13_ _14_ _15_ _16_  17  _18_ _19_ _20_    ]
    _prev_ , _next_ page[ _...12_ _13_ _14_ _15_ _16_ _17_  18  _19_ _20_    ]
    _prev_ , _next_ page[ _...12_ _13_ _14_ _15_ _16_ _17_ _18_  19  _20_    ]
    _prev_          page[ _...12_ _13_ _14_ _15_ _16_ _17_ _18_ _19_  20     ]
Note that the output reflects one-based indices even though the input
page number is zero-based and the href values will reference zero-based
indices. Also note that the url prefix arg should be HTML escaped if it
needs it. This method just slaps an int on the end and considers the
result to be valid for an href value.
For sufficiently small result sets, fewer than eight links may be shown.
For results sets having only three pages, only the prev/next links need to be
shown for the second page (as numbered 1/3 links are overly redundant). Result
sets having only (one or) two pages need not show numbered pages links either.
Input is not validated. Caller is expected to have ensured sensible args.
The set size must be positive. The page size must be positive. The current
page must be non-negative and less than number of pages (which is calculated
from the set size and page size... and note that 'less than' is accurate
because the current page is zero-indexed).
sub prepare_resultset_paging {
    my( $set_size, $page_size, $curr_page, $url ) = @_;
    my $margin = 4; # in the midst of a large list, keep this many links on
        # either side of our current page. Shift things about if we're near
        # either end of our large list to keep 2*$margin links available
        # for sufficiently short lists, the margin becomes less relevant
        # and we just show as many links as there are
    # determine how many pages are in the result set
    my $num_pages = int( $set_size / $page_size );
    $num_pages++ if $set_size % $page_size;
    my $max_page = $num_pages - 1; # zero-indexed
    return '' if $curr_page > $max_page; # docs warn that caller shouldn't do this
    my $l_margin = $margin;
    my $r_margin = $margin;
    if ( $curr_page < $l_margin ) {
        my $diff = $l_margin - $curr_page;
        $l_margin -= $diff;
        $r_margin += $diff;
    if ( $curr_page + $r_margin > $max_page ) {
        my $diff = $curr_page + $r_margin - $max_page;
        $r_margin -= $diff;
        while (  $diff--  and  ( $curr_page-$l_margin > 0)  ) {
    my @window = ($curr_page - $l_margin) .. ($curr_page + $r_margin);
    my( $win_links, $prev, $next ) = ( '','','' );
    if (  @window > 3  or  (@window == 3 and $curr_page != 1)  ) {
        $win_links = join( ' ', map {
            $_ == $curr_page
                ? qq{<strong>@{[$_+1]}</strong>}
                : qq{<a href="$url$_#resultset">@{[$_+1]}</a>}
        } @window);
        $win_links =~ s{^(<a [^>]+>)}{$1...} if $window[0];
        $win_links =~ s{</a>\z}{...</a>} if $window[-1] < $max_page;
        $win_links = "; page[<small> $win_links </small>]";
    $prev = qq{<a href="$url@{[$curr_page-1]}#resultset">previous&#160;page</a>} if $curr_page;
    $next = qq{<a href="$url@{[$curr_page+1]}#resultset">next&#160;page</a>} if $curr_page < $max_page;
    return join( ', ', grep {$_} ($prev, $next) ).$win_links

Tuesday May 20, 2003
03:53 PM

Perl 6 Essentials

Oh Goodie!

Oh Goodie!

Oh Goodie!

I can't wait!


How about a poll: How many editions of Perl 6 Essentials will be released before Perl 6.0?

a) zero: O'Reilly isn't really releasing this edition yet
b) just this one
c) N (because constants other than zero and one are icky)


Thursday May 01, 2003
02:08 PM

don't RTFM... it's too big

Why Read The F (?:riendly| Manual when you can just RTF Pocket Guide?


(who really did take it that way on first read)

Tuesday March 11, 2003
01:19 PM

Perl job opening posted

Washington Universtiy in Saint Louis (STL, MO, USA)

permanent, full time

read more at If it says 'not available', I'm probably just fixing some dumb typo and waiting for approval. Try again in a few hours.

You can comment here if you want, but the link above tells you how you can actually apply for the position. Do not apply to me. All apps must go through HR.

The code you'd be inheriting is mostly mine, and we're hoping to hire soon enough that I can be around for the transition period. I'm likely leaving at some point in May.


Thursday February 27, 2003
05:13 PM

book shopping bookmarklets

This is in reply to a thread on boycotting Amazon. I'd suggested my favorite alternative store and thought I'd follow up with a few bookmarklets which make book shopping simple.

First, know that I use Amazon to window shop. Their features make this so easy and interesting that I can't helpmyself. However, I prefer to shop where I get the best deal (and since Amazon never seems to have the best deal, I've never run into the 'boycott Amazon' issue). The following bookmarklets make it easy for me to window shop at amazon and then go somewhere else when I've found the book I want.

A bookmarklet is just a bookmark with a javascript URL. strips javascript URLs from links, so I'll have to just dump the URLs here raw rather than letting you right-click and bookmark them. Sorry about that.

My favorite online bookstore is They're cheap, they're efficient, and they've never messed up any of my many orders. (I order books online every few weeks, on average.) Their site is very minimalistic (like Amazon was back in the early days). The only glitch is that they don't list books not-yet-in-print, which most other online bookstores do.

I also like to comparison shop with other bookstores on occasion. However, alldirect is so often the best choice (and other stores so much less efficient or reliable) that I generally just go to alldirect.

I've got four book shopping bookmarklets on my Mozilla personal toolbar. They look like this:

    z2a  z2$  a2z  a2$

In my mind amaZon is 'z', alldirect is 'a', and my favorite bookstore comparison shopper is '$'. When I'm looking at a book's page on amazon, I can click 'z2a' to find that book at or I can comparison shop by clicking 'z2$'. If I happen to be looking at a book's page on, I can switch over to amazon with 'a2z' (maybe to find related titles) or to comparison shop with 'a2$'.

The comparison shopping searches will include shipping costs, provided you can tell the script where you'll be shipping to. To figure that part out, go to their home page and fill in your shipping destination, state (for taxes), and currency (ie: USD). Then run a search for any old thing. Look at your resulting URL. Note the bits that look like


You'll want to take your curency/location/state values and use them in the 'z2$' and 'a2$' bookmarklets below instead of my values.

Also note that the following bookmarklets work for me, in my browser. I use Mozilla. If you use some other browser, you may find that these bookmarklets don't work. In that case, you'll need to adapt my javascript to work for your browser. A good way to do this would be to find some example bookmarklets which do work in your browser, and adapt them to use the code below. This page has an 'Up a Directory' bookmarklet in a number of forms for different browsers. That bookmarklet also changes the window's URL and would probably be a good starting point if you find a version that works for your browser.

And now for the bookmarklets. will wrap these javascript URLs because they're so long. You'll need to remove the whitespace.

z2a  click from an book page to the page
javascript:void(location.href=(""+loc ation.href.substr(location.href.indexOf("/ASIN/")+6,10)))
z2$  click from an book page to comparison shopping
javascript:void(location.href=(" type=ISBN&dispCurr=USD&location=10000&state=OR&query="+location.href.substr(loca tion.href.indexOf("/ASIN/")+6,10)))
a2z  click from an book page to the page
javascript:void(location.href=("" +location.href.substr(location.href.indexOf("isbn=")+5,10)))
a2$  click from an book page to comparison shopping
javascript:void(location.href=(" type=ISBN&dispCurr=USD&location=10000&state=OR&query="+location.href.substr(loca tion.href.indexOf("isbn=")+5,10)))

Happy shopping, and happy reading :)


Update 2003_03_23:

Amazon no longer uses /ASIN/ in their URLs, but instead prefers to use /-/ in that place. The following bookmarklets take that into account...

z2a  click from an book page to the page
javascript:void(location.href=(""+locat ion.href.substr(location.href.indexOf("/-/")+3,10)))
z2$  click from an book page to comparison shopping
javascript:void(location.href=(" pe=ISBN&dispCurr=USD&location=10000&state=OR&query="+location.href.substr(locati on.href.indexOf("/-/")+3,10)))
a2z  click from an book page to the page
javascript:void(location.href=(" l/-/"+location.href.substr(location.href.indexOf("isbn=")+5,10)))
a2$  click from an book page to comparison shopping
javascript:void(location.href=(" pe=ISBN&dispCurr=USD&location=10000&state=OR&query="+location.href.substr(locati on.href.indexOf("isbn=")+5,10)))

Friday February 21, 2003
09:24 AM

hiring a perl geek

About three months from now, some perl programmer will have my job, and I'll be unemployed... or so I hope.

Currently I spend most of my time documenting procedures and practices and reviewing existing code and code-level documentation with two coworkers who will inherit said code. They're both relatively new to perl. They've each written two or three perl scripts, and are otherwise primarily Uniface programmers (think "visual basic database apps" but w/o microsoft).

I learned yesterday that managment has agreed that it would be wise to hire a perl person as my replacement. They also agreed that it would be ideal if this person could be hired before I leave. So, I'm in the novel (for me) position of having some say in hiring my replacement, and being the primary person to evaluate their technical qualifications.

We'll be asking for code samples. I'm thinking that I'd like to see something over 100 lines to get a sense of what sort of documentation they typically include, how focused and reusable their subs are, whether they copy/paste instead of using subs/modules, etc. I'll also be asking some perl questions to get a feel for how familiar they are with common idioms, how they approach problems, how well they can take in someone else's code (mainly my code, since that's most of what they'll be working with for a while).

I've already got some questions/problems in mind, but I'm wondering if anyone has input about what sorts of questions they've found useful or useless in the past (from the perspective of the employer) and also whether folks have input from the perspective of the interviewee. Feel free to throw in non-technical questions if you'd like. I'll be asking some communication-skills-type questions too.

Also, does anyone have input about soliciting/reviewing code samples? What sorts of code have you requested (or had requested of you), or was the request always stated in very general terms? What sorts of things did you look for in the code?

If things move smoothly, I expect we'll be looking at resumes within a couple of weeks. Depending on the quantity and quality of applicants we may begin interviewing anywhere from three weeks to ??? from now. In any case, I've got some time before interviews and reviews of code would begin.

Any input? :)

Oh, for the curious, this would be in Saint Louis, MO (USA). I can't say more than that as all of the applications need to go through HR for legal reasons (so don't send me any resumes/code). Yes, I will be posting this opening to relevant perl fora once I've been cleared to do so... probably the perl jobs list, and to, and in this journal. I'll look to see if perlmonks has an appropriate section too. I expect I'll be able to do that some time next week (maybe later if HR needs to clear the exact text I use in the posting).


Update: the position is now available.

Monday February 03, 2003
02:21 PM

it's a verb too

perl (pûrl)


  1. your favorite programming language
  2. the interpreter of your favorite programming language

v. intr. perled, perling, perls

  1. to work in/with perl

v. tr.

  1. to modify using perl
  2. to analyze/examine/study using perl
  3. to re-create/duplicate/prototype using perl
  4. to convincingly demonstrate the benefits of using perl

This weekend I found myself using perl as a verb. Am I alone?


Sunday January 05, 2003
12:22 PM

jotto resources

in response to an article in The Perl Review...

I also got interested in Jotto a while back. A friend had showed me how to play and I wanted to show another friend, but I found it frustrating discussing strategies when I knew the word I wanted them to guess. So, I wrote a script to play against.
        Interface rather undocumented

The script allows you to track most of the things you normally want to track on paper when playing without a computer. If you want to play in a masochistic fashion, you can ignore all those interface elements.

Here's my jott-counting code if you're interested

    sub get_jotts {
        my($probe, $target) = @_;
        my %letters;
        for ( split('',$target) )
            { $letters{$_}++ };
        my $jotts = 0;
        for ( split('',$probe)  )
            {$jotts++ if $letters{$_}-- > 0};
        return $jotts;

Someone on a FWP list pointed out that you can optimize by generating a sub specific to the target word that in contexts where the sub will be called repeatedly with a single target word.

I've got a mammoth live-letter words list at

I use a subset of that for my jotto game

I heard of the "killer" strategy for winning Jotto on the FWP list, and found it too boring to play against, so didn't bother with a head-to-head play version. The basic notion is that every guess must be a possible win. Every time the computer guesses, it must make a guess that could be the target word in light of the scores of previous guesses.

        select a number N between 1..5
        Sort dictionary, first by rough order of word commonality
                                          then by the Nth letter
                                          This will ensure that guesses use more
                                          common words before obscure ones, and
                                          that guesses aren't always alphabetically
                                          early... makes play a pinch more "real"
        for each probe in dictionary
                next PROBE if we've already guessed this probe
                for each term in our history of guesses
                        next PROBE unless score given to term was
                                the same as it would get if probe were target
                if we get here, probe fits all term's scores
                        so return probe as our next guess
        if we get here, no probe worked
                        so we don't know the word (or user mis-scored us)

In practice, the above method gives very little chance for a human to win, and so I didn't find it very fun to play against.

Happy jotting. :)