Feeds:
Posts
Comments

Archive for the ‘Perl’ Category

Replacing sed

I’ve spoken about processing logfiles with perl previously. Occasionally though, I still reach for sed.

Say I have a logfile that looks like this:

[ <timestamp> ] : somefunc()
[ <timestamp> ] : interesting line 1
[ <timestamp> ] : interesting line 2
... 1000s of lines
[ <timestamp> ] : somefunc()
[ <timestamp> ] : interesting line 1
[ <timestamp> ] : interesting line 2
... 1000s of lines

Picking out lines following a pattern is easy with sed – p prints the current match and n takes the next line.

$ < log.txt sed -n '/somefunc()/ {p;n;p;n;p}'
[ <timestamp> ] : somefunc()
[ <timestamp> ] : interesting line 1
[ <timestamp> ] : interesting line 2
[ <timestamp> ] : somefunc()
[ <timestamp> ] : interesting line 1
[ <timestamp> ] : interesting line 2

My first attempt to replace that with perl looks a bit ugly

< log.txt \
perl -ne 'if (/somefunc\(\)/) {print; print scalar(<>) for (1..2)}'

I’m not that happy with the module I came up with to hide the messiness either.

package Logfiles;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(process);

use Carp;

sub process (&$;$)
{
    my ($sub, $regex, $lines) = @_;
    $lines ||= 0;
    return unless /$regex/;
    if (! $lines) {
        $sub->($_);
    } else {
        croak "process() arg 3 not ref ARRAY" unless ref($lines) eq 'ARRAY';
        my $line = 0;
        my @lines = @$lines;
        while (1) {
            if ($lines[0] == $line) {
                $sub->($_);
                shift @lines;
            }
            ++$line;
            last if ($line > $lines[0] or (not @lines));
            $_ = <>;
        }
    }
}

1;

But at least my typical spelunking looks a little cleaner now.

< log.txt perl -MLogfiles=process -ne \
    'process { print } qr/somefunc\(\)/, [0..2]'

Any suggestions on how to improve this (without reverting to sed)?

Read Full Post »

Moose Types

Rants about generalisations notwithstanding, I’m a fan of typeful programming (I’m sure I’d love Ada). For a script that will be moderately complex, I like to sit down and think about the types I’m going to use before I start.

Any library that will enable me to specify my types more precisely and concisely is obviously a win.

And speaking of Moose…

Moose has a bunch of methods to specify your types and a built-in type hierarchy available that you can build off.

Abusing an example I’ve used before:

use Moose;
use Moose::Util::TypeConstraints;
use MooseX::Params::Validate;

subtype 'LegalDrinkingAge'
    => as 'Int'
    => where { $_ >= 18 }
;

coerce 'LegalDrinkingAge'
    => from 'Int'
    => via { 1 }
;

sub can_legally_drink
{
    my $age = pos_validated_list(
        \@_,
        { isa => 'LegalDrinkingAge' },
    );

    return 1;
}

print can_legally_drink(18), "\n";
print can_legally_drink(17), "\n";

Checking for a LegalDrinkingAge type here is obviously the wrong thing to do, but for the purposes of the example it will do.

The resulting error is fine, if a little ugly.

$ perl5.10.1 moose-types.pl
1
Parameter #1 ("17") to main::can_legally_drink did not pass the 'checking type constraint for LegalDrinkingAge' callback
 at /u/packages/lib/perl5/site_perl/5.10.1/MooseX/Params/Validate.pm line 168
        MooseX::Params::Validate::pos_validated_list('ARRAY(0x976ce40)', 'HASH(0x911b6f8)') called at moose-types.pl line 24
        main::can_legally_drink(17) called at moose-types.pl line 33

Read Full Post »

I wouldn’t get into google (their interviews don’t select for my brand of genius). But that’s fine as I wouldn’t be able to write perl there anyway.

I was trying to think of a few reasons why Google would have chosen Python over Perl as their primary scripting language. A number of the ones I came up with are less relevant than they used to be.

Python integrates better with C++

Boost.Python promises seamless interoperability between the two languages. It has been a while since I’ve been tempted to embed a scripting language in my C++ apps so I’m not sure what the counterpart is in Perl if any.

Python "threads"

Back in the day, these were better than the Perl offering. More recently, on Unix at least; with Coro, AnyEvent, Twisted, etc. it’s a wash.

Windows Implementation

A few years ago, the various Perl Windows implementations were not very high quality. Strawberry Perl has changed all that though. It’s awesome.

Jython et el.

Was Jython around when Google was choosing Python? I guess it was.

Perl (5) hasn’t escaped its VM as well as Python and Ruby. Having said that, the Jythons and JRubys of the world are always second class citizens compared to the original C VM as no-one can be bothered to rewrite all the C extensions.

Easier to avoid making a mess as a secondary language?

Experts in either language can write clean, efficient code. But what about folks who are expert in C++ and Java and use either Perl or Python on the side and only occasionally?

I think such usage for a large system will result in unwieldy code in either language, unless the large system is curated by experts, but for small to medium systems in the absence of experts, python may have the edge.

Rabid anti-Perlism

Even smart folks I know seem to think Perl is lacking in some way in comparison to Python. I haven’t managed to get them to enumerate any reasons though so I figure they are speaking from a position of ignorance. This could have been the case for the folks making the decisions for google too or, more likely, they may have considered some of the other reasons on my list.

Read Full Post »

I’m subscribed to Ironman Perl’s full Atom feed in google reader. Most posts display nicely, especially if they use embedded css like mine (boo – bad practice Jared) ;)

However, it seems as though there is some strange interaction between certain feeds, Ironman and Google Reader. Take a look at this post from Mark Fowler:

Ironman Perl in Google Reader

Everything has been stripped, even the paragraphs and line feeds.

At first I thought it was only feeds burned with feedburner, but it isn’t as simple as that.

Another minor nit: detection of the word perl isn’t done at the beginning and end of the words. Hence, properly would cause a post to show up in the feed, even if it has nothing to do with perl.

Read Full Post »

More on REPLs

Most people who think they want a REPL don’t actually want a REPL. It is what a REPL can give them – a Perl (or a Python or a Ruby) machine to which you can add functionality a bit at a time.

For an emacser like me, a sufficiently flexible command-line REPL can give me that incrementally adaptable machine. For most people, a graphical interface to that machine would probably be better.

And thanks, folks, for the suggestions of REPLs to take a look at. No doubt I’ll get around to evaluating a few of them at some point.

Read Full Post »

The Problem with Scripting Language REPLs

I figured out what the problem is with Devel::REPL and the command line REPLs provided by Python and Ruby – evaluation is not a separate step. When I press enter, I’m forced to evaluate the current line.

Yes, you say, that is what REPL means – Read, Evalute, Print, Loop. Evaluate comes after Read.

In reality, usable REPLs, such as Emacs1, let you control when the read evaluate print sequence happens. I can craft the most beautiful function I can think of. Better still, if I change my mind, I can easily modify the function and redefine it with a keystroke. Well, a key chord at least.

In contrast, with Devel::REPL, once I have pressed enter, changing my mind is painful. Integrating it with Emacs comint will probably alleviate a lot of that pain.

Or better yet, as Anonymous recommends, I should take a look at Sepia or PDE which already have emacs integration. Having said that, basic integration is, what, 20 lines of emacs-lisp?


1. Yes, Emacs is a REPL. Kinda.

Read Full Post »

I’m somewhat amused at one of the more recent comments here – Nathan L. Walls defends his "choice" of Ruby with some very woolly justifications (emphasis mine):

"Ruby’s community feels more vibrant. No, not something you can measure. It is a feeling."

"Yes, there are equivalents in Perl, but they are far rougher. Again, not really measurable, but a feeling."

Of course, his day job is still writing Perl. Moving swiftly on…

Devel::Repl

The main thing I got out of the comment apart from a chuckle, was it motivated me to look at Devel::REPL.

One of the other main tools in my toolbox is emacs and when writing emacs lisp, I make full use of the REPL. But I’ve never even wanted an equivalent in Perl.

One cpanm invocation later and I’m ready.

Wait, no I’m not. I copied Caleb’s repl.rc config to make it more usable. I added MultiLine::PPI which resulted in a bunch of errors at start-up. It turns out I need to add File::Next and B::Keywords separately.

$ cpanm File::Next
$ cpanm B::Keywords

Okay, now I’m good to go.

First REPL session

$ jared@localhost $ re.pl
$ sub f
$ {
> say 'h';
> say 'hello';
> }
h
hello
1 $ f();
Runtime error: Undefined subroutine &Devel::REPL::Plugin::Packages::DefaultScratchpad::f called at (eval 290) line 5.
$ sub f {
> say 'h';
> say 'hello';
> }
$ f();
h
hello
1 $

It still isn’t quite perfect. But to be honest, I find it (and the Python and irb REPLs) pretty useless. I probably need to look into integrating it with emacs comint.

Read Full Post »

« Newer Posts - Older Posts »

Follow

Get every new post delivered to your Inbox.