A popular lament heard from business is "It's difficult to find Perl 5 programmers!"
I can imagine that it's difficult to find good Perl 5 programmers. most of the really good ones I know have full-time equivalent employment (and plenty don't want to move to the greater London metro area for 20,000 GBP per year or San Francisco for $40,000 a year). It's also difficult to evaluate the skill of any self-proclaimed Perl 5 programmer; it's easy to write baby Perl, but it's not always easy to know how to become a better Perl programmer.
Three possibilities present themselves:
- Improve the ways in which they compete to find good Perl 5 programmers, such as offering larger salaries or telecommuting or better perquisites. (Few companies do this.)
- Give up. (Anecdotal evidence suggests some companies have done this; it's easy to throw a few thousand dollars a year to find cheap PHP development.)
- Train good programmers.
Five years ago, the latter might have been daunting. Now I can imagine that a motivated consultant could put together a customized hiring and training course for a specific company in a specific industry to identify the skills necessary (Perl and otherwise) for new hires as well as the skills necessary for existing developers.
I can imagine that new employees should read Perl Best Practices and should walk through Perl::Critic policies on their first day. I would love to see them handed a copy of Effective Perl Programming, 2e.
Perhaps I demonstrate no small hubris, but I hope that Modern Perl: The Book can fill in any of the gaps of an experienced (but still novice) Perl 5 programmer as well as explain how Perl 5 works to a new Perl 5 programmer. In short, my intent with the book is to help novices and neophytes become adepts. I believe we can achieve similar things with many of the tools developed during the Perl renaissance.
The important question is how to convince businesses to take advantage of this renaissance. In effect, we have to demonstrate that (like many other job skills) Perl 5 is something easy and effective to teach a motivated worker.
5 July, 2010 i
jobs,
modernperl,
perl,
perl5,
training |
Comments Off
Class::Struct has been a core module for ages. (Previously it was Class::Template, but a great renaming occurred 13 years ago.) If you've never seen it before, it might remind you a little bit of Moose:
package Cat;
use Class::Struct;
struct( name => '$', age => '$', diet => '$' );
You don't get all of the benefits of Moose, but you do get attributes and accessors. You also get a default constructor.
Of course, the default constructor reads something like:
{
package Cat;
use Carp;
sub new
{
my ($class, %init) = @_;
$class = __PACKAGE__ unless @_;
...
}
...
}
If that emboldened line is curious to you, it's curious to me too. I saw a note in one of the test files somewhere suggesting that the purpose of this was to allow you to write:
package Cat;
my $cat = new();
I don't know why you'd do that, however. In what kind of object design does
it make sense to create objects of a class from within that class? (That seems
like a violation of responsibilities to me.) You can also write:
package NotCat;
my $cat = Cat::new();
... though that's exceedingly fragile. For one thing, it implies that you could also write RobotCat::new()—assuming that RobotCat extends Cat, but avoiding method dispatch for calling a constructor means that RobotCat had better provide its own new() which behaves as a function as well as a method. (Even if you somehow convinced the subclass to inherit the superclass's function through some sort of exporting scheme, the hardcoded __PACKAGE__ would hurt.)
Hardcoding a method dispatch as a function dispatch means that the maintainers of Cat are not free to change how Cat provides its constructor, much for the same reason.
Woe unto you if there's an inherited AUTOLOAD somewhere.
I realize that in 1994 or 1995, people who wrote OO code in Perl 5 might
have had familiarity with OO in C++ (where this syntax makes a little more
sense) or, perhaps, Java where the indirect constructor call (the my Cat
$cat = new Cat; is prevalent), but the benefit of hindsight is that
experienced Perl 5 programmers can look back on this API a decade later and
cringe at its potential for misuse.
If you're lucky, everything will go right—but what kind of a defensive programmer relies on luck when designing an API?
2 July, 2010 i
apis,
design,
modernperl,
oo,
oop,
perl,
perl5 |
Comments Off
In addition to the job vacancy in West LA, the company I work for, TigerLead.com, has an opening for a “skilled developer” in Ann Arbor, Michigan:
Our work involves manipulating and warehousing external data feeds and developing web interfaces to create home search tools for prospective buyers and lead management tools for real estate agents. We’re looking for a skilled coder to join our small team of talented engineers in Ann Arbor. We hope to find an experienced programmer who is a good fit with our team, well-versed in multiple languages, able to learn quickly and work independently. We work in a Linux environment, and tools and languages we use include Perl, Ruby on Rails, PostgreSQL, and GIT. Perl experience is a significant plus, but your current comfort level with any of these specific tools is less important than overall technical aptitude and ability to learn quickly and fit in well with the current team.
That’s a little thin on details partly because the work is varied. If you think you might be interested, take a look at the full job posting.
TigerLead is a lovely company to work for and this is a great opportunity. Highly recommended.
Filed under:
software Tagged:
jobs,
perl,
postgresql,
ruby
2 July, 2010 i
jobs,
perl,
postgresql,
ruby,
software |
Comments Off
The company I work for, TigerLead.com, has an opening for a “skilled coder / database wrangler”.
We’re looking for a skilled coder / database wrangler to play a key role within our Operations and Engineering teams. The various responsibilities of the job include working with the large databases underlying our real estate search tools, setting up services for new clients, communicating with clients to evaluate bug reports, troubleshooting technical issues escalated by our client services team, and interfacing with the engineering team on systems maintenance and development. The scope of work that we do involves managing hundreds of external data feeds that feed into in-house databases totaling several million property listings. These listing databases power hundreds of real estate search sites used by more than a million home-buyer leads, who are tracked and cultivated by the thousands of Realtors using our management software. This position is critical to the robustness of these systems.
If that sounds like interesting work to you then take a look at the full job posting.
TigerLead is a lovely company to work for and this is a great opportunity. Highly recommended.
Filed under:
software Tagged:
jobs,
perl,
postgresql,
ruby
2 July, 2010 i
jobs,
perl,
postgresql,
ruby,
software |
Comments Off
I use Moose to explain object orientation in Perl in the Modern Perl book. It's much easier to explain the what and why of OO with syntax like:
{
package Cat;
use Moose;
has 'name', is => 'ro', isa => 'Str';
has 'age', is => 'ro', isa => 'Int';
has 'diet', is => 'rw';
}
... than the corresponding code where you must write your own accessors, poke into a blessed hash directly (and bless it yourself), perform your own coercions and verifications, and the like.
Of course, the preferred syntax for doing this within the Moose documentation is different from how I've done things. Moose recommends:
{
package Cat;
use Moose;
has 'name' => (is => 'ro', isa => 'Str');
has 'age' => (is => 'ro', isa => 'Int');
has 'diet' => (is => 'rw');
}
Sometimes you quote the name of the attribute and sometimes you don't.
Should I drop the parentheses? Should I drop the fat arrow between the name of the attribute and its specializers? I do in my own Moose code for my preferences, and I did in the book. Then I thought about it and realized why I write code this way.
First, a digression. Perrin Harkins mentioned the inability of the "Takes a block!" prototype to replicate builtin syntaxes as a reason to dislike syntax-bending modules such as Error. For example:
use Error ':try';
try
{
...
}
catch
{
...
};
... really needs that trailing semicolon. For similar reasons,
many modules which use Devel::Declare magic
go through contortions to add trailing commas and semicolons. Perl 5's syntax
is malleable, but when the parser wants something from the lexer, it really
really wants something from the lexer. (When it wants to know that a statement
or a group of terms has ended, you don't get to lie.)
In other words, even though you have a lot of options for mangling Perl 5's
syntax any way you like it, the semantics of the host language will shine
through. A parenthesis is a parenthesis. A labeled block is a labeled block.
A bare sub { ... } is never an expression on its own, and it can
never terminate an outer expression.
This is one of the downfalls of the so-called "embedded domain specific
languages". If you haven't written your own parser, you'll have to take what
you can get. This is even true if you do write a parser and generate
and eval code, and it's especially true if your EDSL desugars to
chained function or method calls.
I'm not suggesting a flaw with Moose's approach: it's clever and Perlish and
doesn't succumb to the saccharine cutery of so many other so-called DSLs. (To
my knowledge, no one in the Moose world has claimed it's anything other than
Perl 5 syntax bent slightly into something which looks declarative enough.)
My concern—especially when explaining object orientation in Perl 5 to
novices—is that any extra syntactic elements might confuse people to
think that they mean more than they mean. You and I might both understand that
the grouping parentheses in the Cat attribute declaration are
merely visual hints to the reader that the specializers are subordinate to the
attribute itself and that the fat arrow between the name of the attribute and
its grouped specializers confers the notion of pairing between the attribute
and its specializers, but how do you explain that to someone who's still
struggling to figure out what this encapsulation thing is all about?
I've attempted caution throughout the book such that the fat comma always signifies a pairish relationship, such as for hash keys or named arguments. Certainly you can always use it in place of the skinny comma (and, barring any quoting changes, vice versa), but is it clear to do so?
Likewise, you can wrap parentheses around almost any old rvalue (barring precedence changes) and not change the behavior of lists, yet this confuses novices all the time:
my @lololol = ( 1, 2, ( 3, 4, (5, 6) ) );
I'm not criticizing the Moose documentation or the standard approaches to formatting Moose code. I'm not suggesting a change. I don't like deviating from community standards for declaring Moose attributes. Even so, avoiding the need to explain the equivalencies of syntax to people for whom learning syntax is still a really big deal is itself to me a big deal.
I love it when people post patches to RT, but I don't really like the work required to download them from the web interface. I know there's an rt command line client somewhere, but the last time I tried it, it didn't work very well for me. Thankfully, with the help of RT::Client::REST, I whipped up a short program that will take a ticket number, pluck my credentials from my .pause file, and save the attachments into the current directory.
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use autodie;
use Encode qw/decode/;
use Error qw(:try);
use Path::Class;
use RT::Client::REST;
use RT::Client::REST::Ticket;
my %credential = split " ", file($ENV{HOME}, '.pause')->slurp;
my $user = lc $credential{user};
my $pass = $credential{password};
my $id = shift(@ARGV) || die "No ticket # provided";
$id =~ s{^(?:rt#?)}{};
die "Ticket must be an integer" if $id =~ /\D/;
my $rt = RT::Client::REST->new(
server => 'http://rt.cpan.org/',
timeout => 30,
);
try {
$rt->login(username => $user, password => $pass);
} catch Exception::Class::Base with {
die "problem logging in: ", shift->message;
};
my $ticket;
try {
$ticket = RT::Client::REST::Ticket->new( rt => $rt, id => $id);
} catch RT::Client::REST::UnauthorizedActionException with {
print "You are not authorized to view ticket $id\n";
} catch RT::Client::REST::Exception with {
die "problem getting $id, ", shift->message;
};
try {
my $iter = $ticket->attachments->get_iterator;
while ( my $i = $iter->() ) {
$i->retrieve;
my $name = $i->file_name or next;
my $encoding = $i->content_encoding;
$encoding = '' if $encoding eq 'none';
my $string = $encoding ?
decode( $encoding, $i->content, 1 ) : $i->content;
say "Writing $name";
file($name)->openw->printflush($string);
}
} catch RT::Client::REST::Exception with {
die "problem getting attachments from $id, ", shift->message;
};
This is mostly just some cut/paste/modify work with the relevant synopses in the documentation. There was a little trial-and-error required, particularly in how encoding was being passed through, but it seems to work. I was able to download a patch while connected via ssh, which is exactly what I was looking for.
Update: I fixed a hardcoded "#10" in an error message.
1 July, 2010 i
ironman,
perl programming |
Comments Off
Last week at YAPC I finished editing the draft of Modern Perl: The Book.
I'm pleased with how it's turned out, but I'm not yet ready to hit the "Ship it to stores!" button. In particular, I could use your help:
- Is the material accurate?
- Is the material effective in its explanations?
- Are any parts confusing?
- Is the material comprehensive?
- Are there typos or infelicities?
- Are the cross references appropriate?
- Is the organization and order sensible?
You can always render the latest version of the book from a Github checkout by running perl build/tools/build_chapters.pl and perl build/tools/build_html.pl. You must install Pod::PseudoPod to build the HTML. The easiest way to install Pod::PseudoPod is to install cpanminus, either with your packaging system or with commands like:
cd ~/bin
wget http://xrl.us/cpanm
chmod +x cpanm
Then run cpanm Pod::PseudoPod.
I've also uploaded the file to the drafts section of this website: Modern Perl draft book.
I welcome any and all feedback. You're more than welcome to contact me directly, but the easiest mechanism for me to receive feedback is in the form of bug reports, patches, and pull requests on Github. Please feel free to add your contact information to the CREDITS file if you prepare a patch, even for the simplest typo. Gratitude is important and I have much to share.
We plan to send the book to the printer sometime in August, and we'll certainly make PDFs and ePub versions available as well. For now, please don't redistribute the book; please instead distribute links to the book.
The draft chapters are:
- The Perl Philosophy
- Perl and Its Community
- The Perl Language
- Operators
- Functions
- Regular Expressions
- Objects
- Stylish Perl
- Writing Real Programs
- Perl Beyond Syntax
- What to Avoid
- What's Missing
29 June, 2010 i
books,
drafts,
modernperl,
onyxneon,
perl,
perl5 |
Comments Off
Overheard at YAPC last night:
Person one: I can't find Try::Tiny exciting.
Person two: Isn't promoting that admitting that Perl 5's exception handling is broken?
(Perl 5.13.1 introduced improvements to Perl 5 exception handling. They
need more testing on existing code, but the Perl 5.14 release next year will
likely include them. The existence of Try::Tiny has directly
produced language improvements; in this case the cycle works.)
I like Try::Tiny; it simplifies exception handling in Perl 5.
Handling exceptions correctly (even in 5.12) is difficult. That's
primarily a syntax issue. You can handle exceptions
correctly—Perl 5 provides all of the tools necessary to do so—but
it's not simple to read or to write.
Similarly, runtime type reflection is difficult: ref is
unreliable and the standard hacks for abusing UNIVERSAL::isa are
far too often wrong.
Try::Tiny is nice because it offers good syntax which hides all of the internal complexity Perl 5 exposes. A world with T::T is better than a world without it.
Even so, Try::Tiny is only useful to people who know that it
exists, who can install it, and who make use of it pervasively.
Try::Tiny isn't useful for people who don't know it exists. In
other words, Try::Tiny isn't useful for novices. It
could be and it should be, but novices aren't going to hear
about it. (Some will, but how many novice Perl developers know about the CPAN?
How many novices have joined the Perl community sufficiently that they can
learn from the hard-won wisdom of Perl adepts? Vanishingly few, as they do not
remain novices for long.)
Here's the virtuous dilemma: isn't it nice to have a language with a working
and well maintained extension mechanism? Isn't it nice to be able to
modify our own languages in our own lexical scopes? Yet when our language
modifications improve basic language features—instead of adding
new language features—should we praise them as victories instead of
acknowledging them for the patches and bugfixes that they are?
Yes, changing how exception handling works in Perl 5 now, especially if it
requires semantic changes, may cause some pain. (It may also fix undiscovered
bugs in existing programs, which is a virtue of its own.) Yet isn't the
ability to modify the language for your own purposes sometimes akin to running
a patched version of the language itself?
Yes, it's safer and more composable, and less permanent than running a
patched binary, but still....
23 June, 2010 i
languagedesign,
modernperl,
perl,
perl5 |
Comments Off
I've released a new version of Capture::Tiny, which now catches exceptions, cleans up file handles, then rethrows the exception. This is the first major bug-fix in a while and was easy to address.
I'm feeling pretty confident that Capture::Tiny is a robust, cross-platform answer for any sort of output capturing. If you'd like to understand why, the slides from my talk, "How (not) to capture output in Perl", provide an explanation of why most other output capture approaches are flawed and why this is the single best tool for the job.
21 June, 2010 i
ironman,
perl programming |
Comments Off
Paraphrasing Piers Cawley talking about why to give up Ruby for Perl (paraphrased):
This is assembly language for calling a function:
push address of RETURN on stack
push $argument on stack
get address of FUNC
goto FUNC
RETURN:
pop return value off of stack
This is Perl 5 for calling a function:
func($argument);
That's all well and good. This is assembly language for entering a function:
pop parameter from stack
verify parameter type constraints
...
This is Perl 5 for entering a function:
sub func
{
my $parameter = shift;
die 'Wrong type' unless $parameter->isa( 'Whatever' );
...
}
... but wouldn't it be nice if:
sub func(Whatever $parameter) { ... }
(No new insight here, but directly prior to this talk, Damian Conway and I talked about how Perl 6 signatures simplify much, much more code than this simple example illustrates. Lots of code goes away.
21 June, 2010 i
languagedesign,
perl,
perl5,
perl6 |
Comments Off