Stories
Slash Boxes
Comments
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 ]

lachoy (1663)

lachoy
  chris.winters@gmail.com
http://www.cwinters.com/

I am actually Chris Winters; I am actually living in Pittsburgh, Pennsylvania, USA; I am actually married and have three cats. (Guess what one of them is named?) I am the "OpenInteract" guy, which could be good or bad.

Journal of lachoy (1663)

Tuesday August 07, 2007
01:50 PM

Resolved: ignore anyone who says...

"face it" when trying to convince someone of anything. As in, "Let's face it, everybody knows that furbles blorbicate way more than they nooble." Declaring a fact correct doesn't make it so

Inspired by chromatic's recent post, where multiple commenters tried this, like "Face it the main languages used today are Java, C/C++,C#, and Python." or "Face it -- by the time they release it [Perl6] (around the time when Duke Nukem comes out, I'm sure), Ruby will have already overtaken Perl5."

Posted from cwinters.com; read original

Thursday June 07, 2007
04:19 PM

Collections + Generics = autovivification?

One of the many nice things about Perl is autovivification -- you don't need to assume a hash key exists before you can assign to it, as many times as you like. So you can do something like:

my %employees = ();
$employees{'Steve McQueen'}->{salary} = 50000;

And the intermediate hash attached to the key 'Steve McQueen' will be created along the way for you. Now, like a lot of things in Perl this can lead to silent failures -- if I now do this:

my %employees = ();
$employees{'Steve Mcqueen'}->{department} = 'Kicking ass';
                   ^^^

...a whole new hash would be created and the data won't be where I expect. But there are many ways to get around this, most of which you should be doing anyway (case-insensitive keys, IDs as keys, tests, etc.). Perl will let you shoot yourself in the foot.

The equivalent in Java would be:

Map<String,EmployeeData> employees = new HashMap<String,EmployeeData>();
employees.get( "Steve McQueen" ).setSalary( 50000 );

Instead, I need to do:

if ( ! employees.containsKey( "Steve McQueen" ) ) {
   employees.put( "Steve McQueen", new EmployeeData() );
}
employees.get( "Steve McQueen" ).setSalary( 50000 );

Or even more egregious, because all we're asking the language to do is pick a reasonable default implementation of an interface:

Map<Integer,List<Work>> workByID = new HashMap<String,List<Work>>();
Work work = getWorkFromSomewhere();

<p>// one line
workByID.get( 15 ).add( work );

<p>// ...vs four lines
if ( ! workByID.containsKey( 15 ) ) {
   workByID.put( 15, new ArrayList<Work>() );
}
workByID.get( 15 ).add( work );

I know some frameworks do this -- in particular, object creation frameworks that map data coming in (over HTTP, via an XML/JSON graph, etc.) to objects. But should you really need a framework for this, each with its own quirks? (Yes, OGNL, or at least OGNL + Webwork, is quirky.) Shouldn't the language and data structure be smart enough to figure that it can pick a reasonable List implementation for you if there's none specified by use? Or that it can use the no-arg constructor for random JavaBeans?

It winds up encouraging the use of lots of little classes. By itself that's not such a bad thing, I'm a fan of using lots of little classes. But not when most of them do no more than add null checks to the standard library's data structures.

Posted from cwinters.com; read original

Wednesday April 04, 2007
12:43 PM

A couple of the things I miss most from perl...

At this point in my career I'm probably 50/50 in the time I've spent using Java and Perl. When I first got into Java my brain tried to map Perlisms to Java, but I think I'm now fluent to the same degree in each.

That said, even after six years of doing Java FT there are still some things from Perl I dearly miss, and they break down into syntax and constructs.

Syntax: And I've said many times that, barring extreme cases, disliking a language because of its syntax is like disliking a spoken language because of a dialect. After a while of reading or hearing it, you get acclimated. What was once jarring becomes the norm.

That said, the things I miss most are next, last, and unless. The first two are just lingo preferences both: next and last are more humane (and informational) than their equivalents, continue, and break. (Seeing 'break' in a program is still occasionally funny, as if you're attempting to induce a random bug with a single verb.)

But unless is different. One of my pet peeves with Java libraries is that there's never an 'isNot' for every 'is' property. So you wind up mixing metaphors, using a terse negation operator with a verbose boolean property invoked as a method. For example, if I wanted to process a list only if it had data, I'd do:

List thingies = getThingies();
if <b>( ! thingies.isEmpty() )</b> {
   // do stuff with thingies
}

Besides the mixing metaphors, there's more of a logistical problem (and source of a future rant): with most developers' weird whitespace preferences, the negation becomes very difficult to see because it's rendered as:

List thingies = getThingies();
if <b>(!thingies.isEmpty())</b> {
   // do stuff with thingies
}

Putting the negation in the method is better, either as:

List thingies = getThingies();
if <b>(thingies.isNotEmpty())</b> {
   // do stuff with thingies
}

or you can have a more readable positive version, which suffers because it's not a valid JavaBean property and therefore either un- or differently-usable by lots of tools and libraries:

List thingies = getThingies();
if <b>(thingies.hasItems())</b> {
   // do stuff with thingies
}

Both of these move the negation right, into the property. Perl moves it left, into the condition declaration:

# assume that $thingies is a list object with methods
my $thingies = get_thingies();
<b>unless ($thingies->is_empty())</b> {
   // do stuff with thingies
}

But that's just the beginning. Where it really shines is with prefix operations in loops where you want to skip items, or stop iterating entirely. To take an example from my daily work, say you have a plan of care for a nursing home resident and you want to only use that plan if the resident is not 'on leave' (out of the home) or discharged. In Java, this might look like:

Listlt;Plan> plans = getPlans();
for ( Plan plan : plans ) {
    <b>if ( plan.getResident().isNotActive() ) {
        continue;
    }</b>
    ...

(Note that a nice object designer put the negative condition as a method!)

I could have put the 'continue' at the end of the line, eliminating the braces, but then it gets lost. Perl gets around this by putting it at the front, so you have:

my @plans = get_plans();
foreach my $plan ( @plans ) {
    <b>next unless ( $plan->resident()->is_active() );</b>
    ...

Reducing the number of lines (from 3 to 1) is secondary to making your intent much clearer, and that's what I dearly miss. One of the 'features' built-in to Perl (and its culture) is TMTOWTDI. It makes non-regular Perl users frustrated, but IMO it can actually make for much more readable programs because your intent can be more clearly stated.

Constructs: The other two items, grep and map are kissing cousins, and represent the ability to do something on a bunch of stuff (an Iterable, in Java terms). That something might be to conditionally include it into another bunch of stuff, or to pull common data out of each of the bunch, or whatever.

There are libraries that kinda-sorta do this (like commons collections or jga), but they're clunky as hell. It's not necessarily their fault, in many cases Java makes this necessary. But the result is the same: the clunkiness discourages the sort of active use that, again, expresses intent much more clearly. For instance, say I wanted to pull out the ID from every resident given the list of plans above. I could do it the long way:

List&lt;Integer> residentIDs = new ArrayList<Integer>();
for ( Plan plan : getPlans() ) {
    residentIDs.add( plan.getResident().getID() );
}

whereas in Perl, it might be:

my @residentIDs = map { $_->resident()->id() } get_plans();

To the uninitiated, map is scary, using the infamous $_ that non-Perl folks seem to instinctively hate at first sight. I always tell them, "Just substitute 'it' where you see dollar-underscore." So your block now reads "get the resident from it, then get the ID from the resident and return that." Not so scary, and after you see it and use it a few times it's second nature -- you get acclimated.

Posted from cwinters.com; read original

Sunday January 28, 2007
06:35 PM

How did you find your jobs?

People always talk about how they want to find jobs, but not that often about how they've actually done it. So here's me.

Before/during college, it was:

  • replying to newspaper ads (bookstore worker/manager, waiter, bartender)
  • tagging along with a buddy who knew somebody (shady 'charity' telemarketing, dishwasher at nursing home, making concrete)
  • knowing my mother (two internships at the National Geographic Society)
  • randomly applying to a job without knowing what was open (Pitt library)

Since college, I've got most of my jobs through responding to want ads. But I suspect that as I get older I'll do that less, just because companies like to hire senior developers they're comfortable with.

1992, Research Assistant: Responding to an ad posted on the Political Science Department bulletin board at Pitt for a position at George Mason University (outside Washington, DC, about 4 hours away). I don't know how widely the ad was circulated, or if they had a lot of applicants for the position.

1993, Transportation Planner: Referral to a family member by someone I worked for. The early 90s were a difficult job market. After my previous position's contract expired I went through a few temp jobs while applying to a ton of jobs and got a few interviews. One temp job was at the Institute of Medicine. I must have done a good job because the woman I worked for gave her husband (who was high up in the Montgomery County Planning Department) my resume, and I got an interview and a position shortly after that. Planning wasn't something I aimed to get into but the writing, research, and public focus group interaction wound up being a pretty good job.

1995, Writer: Found this through a want ad in the Washington Post. I applied because of my experience over the previous two years with transportation -- this was at a non-profit, transit advocacy organization. The main part of the job was writing (articles for a trade magazine, whitepapers, memos), but one thing that set me apart was my familiarity with bulletin board systems (dialup, not internet). The position evolved into more IT stuff as I became the Netware admin, hooked up GroupWise to a single dialup account multiplexed for email, and put the first website up along with some dynamic.

1997, Webmaster: Another Washington Post ad, although I knew someone who worked at the educational non-profit. I'd gained enough experience with the web at the previous job to do it full-time, although I also had to do some helpdesk and other IT work (including building cheapo computers with unfinished metal, ouch).

1998, Software Developer: I started a company with a couple of the guys I worked at in the previous position, so this was definitely through personal connections.

2000, Software Developer: Company found my resume on the Pittsburgh Technology Council website. The position was kind of ill-defined and shortly wound up using Java, which I didn't know going in

2004, SQA: Found posting on Pittsburgh Technology Council website. I didn't have any explicit SQA experience but I was interested in being part of a software process. And I liked the company so much that I figured if SQA didn't work out I could move somewhere else...

2005, Software Developer: ...which happened 9 months later when I applied to a position on a much smaller team looking into new markets for our technology...

2006, Software Developer: ...the first new venture of which was spun off bout 9 months later, where I'm the lead architect on a rewrite of the server-side software.

How about you?

Posted from cwinters.com; read original

Friday December 29, 2006
03:29 PM

Hello to Ella Mae Winters

Ella Mae Winters was brought into the world on December 27 at 10:07 PM, weighing in at a hefty 10 pounds, 1 ounce and 21.5 inches long. Her extra two weeks in the womb were apparently dedicated to making her not only amazingly cute and alert, but also to growing her head of brown hair.

Despite prediction/hope from my last post, the labor was fairly long and at times difficult, but Barb is recovering very well. And Ella has been healthy and very strong throughout, which may be a testament to the prodigious amounts of 8th Continent soymilk that Barb has consumed in the last nine months. (Don't let anyone tell you a mother has to eat meat to produce a big baby!)

About her name: Ella is for my mom (Pamela), who passed away in 1999 and who would be bursting with happiness (and advice!) right about now. Mae is another form for Barb's maternal grandmother's name, Mary. Like all parents, we don't anticipate using both except in exasperation, although the potential pen names ("E. M. Winters", "E. Mae Winters") sound pretty good.

Photos are being uploaded to flickr literally as I type this, and you can subscribe to the all-Ella, all-the-time show as you wish.

Sorry for not following up my last post sooner, but some of these "21st century" hospitals still don't have internet access!

Posted from cwinters.com; read original

Monday December 18, 2006
07:25 AM

Recent book: The Hot Kid, Elmore Leonard

I borrowed The Hot Kid from a co-worker just because it was Elmore Leonard. I haven't read any of his books for a while, but I went through a period in the 90s where I devoured a dozen or so. This one is different: rather than being set in Miami, LA or Detroit, it's in Oklahoma and Kansas. And rather than being 70s/80s/90s/current, it's set in the 30s. But it's still Leonard, through and through.

What does that mean? For one, you know you're getting little exposition and tons of sharp dialogue. So rather than an omniscient narrator telling you that Carl is getting shaky because someone else depends on him for the first time in your life, and rather than relying on the description of his "quavering voice" or that he has to "steady himself on the porch railing", you get it through dialogue. And if you breeze through it you'll miss a lot of subtlety and those turning points where the characters change and grow (or regress).

Recommended.

Posted from cwinters.com; read original

Friday December 01, 2006
12:46 PM

Patent craziness: the linked list

You think I'm kidding? Check it out:

What is claimed is:
1. A computerized list that may be traversed in at least two sequences comprising: a plurality of items that are contained in said computerized list; and a primary pointer and an auxiliary pointer for each of said items of said computerized list such that each of said items has an associated primary pointer and an associated auxiliary pointer, said primary pointer functioning as a primary linked list to direct a computer program to a first following item and defining a first sequence to traverse said computerized list, said auxiliary pointer functioning as an auxiliary linked list to direct said computer program to a second following item and defining a second sequence to traverse said computerized list.

...as if you needed further proof that the patent system is fundamentally broken.

Posted from cwinters.com; read original

Thursday November 09, 2006
10:04 AM

JavaScript talk to pgh.pm

I gave a talk to the Pittsburgh Perl Mongers tonight about JavaScript. So no, every talk doesn't need to be about Perl, although drawing references to perl constructs helps :-) Anyway, here are the slides (PDF, 1.5MB).

Wednesday October 25, 2006
11:55 AM

Small teams++

From "The Business of Software" in the September 2006 Communications of the ACM (abstract), summarizing findings from the 2006 QSM Software Almanac:

The effectiveness of large teams is seriously questioned by the data in this analysis. Large teams (29 people) create around six times as many defects as small teams (three people) and obviously burn through a lot more money. Yet the large team appears to produce about the same amount of output in only an average of 12 days less time....

The "best in class" projects compared to the "worst in class" in this study tracked over the following ranges:

Effort: 15x less effort
Schedule: 1/5 of the duration
Team Size: The "best" teams were much smaller (9% > 10 people, versus 79% > 10 people on the "worst in class" teams).

Posted from cwinters.com; read original

10:59 AM

Removing 'My Bluetooth Places': piece of cake!

From PC World Forums:

To Remove the "My Bluetooth Places" icon from desktop, simply right click on desktop and then go to properties/desktop/customize desktop/clean desktop now. Then tick the box: "My Bluetooth Places" and press next. The icon should then be in a folder called unused desktop items on your desktop. You can then delete the folder if you wish too, it's that easy.

Is it possible that any nomal human would discover this on their own? On a Mac, you know what the instructions would be? "Drag the icon to the trash." It would Just Work.

Posted from cwinters.com; read original