Feeds:
Posts
Comments

Easy Unicode in Perl

Lots of discussion on Unicode in Perl recently.

(I didn’t see any retraction from Nelson, respectful or otherwise, though)

I can’t see what is wrong with the (brand newish) utf8 pragma approach especially when all the issues are ironed out. You don’t want to break backwards compatibility and give folks any more reason not to upgrade to later versions of Perl.

Does Perl need a JIT?

Casey Randberger dropped by to point out that Squeak Smalltalk now has a JIT.

I don’t care about Squeak1, but very occasionally I think it would be nice if Perl got a JIT.

However, I don’t think it would make sense to develop a JIT for Perl.

  • People don’t choose Perl for its speed
  • The reason folks switch from Perl to a competitor2 is not because the competitor is faster (because it isn’t)
  • Even for Python, everyone uses CPython rather than speedy implementation

There’s a lot of reasons I choose Perl, but a JIT would not increase the number of projects where I reach for Perl over C++.


1. It’s not pragmatic enough for me – who would employ me to write Squeak for example

2. Python and Ruby

Streaming Plack

Thanks to Douglas and Jakub for pointing me at the appropriate part of the PSGI spec for streaming.

Miyagawa mentions that plack streaming can be blocking, and running this with Starman demonstrates that nicely.

my $app = sub {
    my $env = shift;

    return sub {
        my $respond = shift;
        my $writer = $respond->([200, ['Content-Type', 'text/html']]);

        for (1..5) {
            my $dt = localtime;
            $writer->write("[ $dt ]
\n"
); sleep 2; } $writer->close(); }; };

Starman attributes include:

'psgi.streaming' => 1,
'psgi.nonblocking' => ''

Firing off two requests at the same time, the second doesn’t start until the first completes.

[ Mon May 30 18:56:16 2011 ]
[ Mon May 30 18:56:18 2011 ]
[ Mon May 30 18:56:20 2011 ]
[ Mon May 30 18:56:22 2011 ]
[ Mon May 30 18:56:24 2011 ]
[ Mon May 30 18:56:26 2011 ]
[ Mon May 30 18:56:28 2011 ]
[ Mon May 30 18:56:30 2011 ]
[ Mon May 30 18:56:32 2011 ]
[ Mon May 30 18:56:34 2011 ]

Even for a curmudgeon like me who doesn’t make much use of object orientation, Moose offers something which supports my programming with types style: a degree of run-time type checking and the ability to create a range of convenience functions with very little code.

Say I have a person who makes a bunch of orders consisting of a bunch of items. My hashref might look something like this:

my $data = {
    fred => {
        orders => [
            {
            order_id => 'fred1',
            items => [
                { description => 'roses' },
            ],
        },
            {
            order_id => 'fred1',
            items => [
                { description => 'one true ring' },
            ],

        },
        ],
    },
};

Then I’ll probably need a bunch of convenience functions to make sure I’m adding items to orders rather than people.

In Moose, including the type checking, that looks like:

Item

package Item;
use Moose;

has description => (
    is => 'ro',
    isa => 'Str',
);

no Moose;
__PACKAGE__->meta->make_immutable;

Order

package Order;
use Moose;

has order_id => (
    is => 'ro',
    isa => 'Str',
    required => 1,
);

has items => (
    is => 'rw',
    isa => 'ArrayRef[Item]',
    default => sub { [] },
    traits  => ['Array'],
    handles => {
        add_item  => 'push',
        get_items => 'elements',
    },
);

no Moose;
__PACKAGE__->meta->make_immutable;

Person

package Person;
use Moose;

has name => (
    is => 'ro',
    isa => 'Str',
    required => 1,
);

has orders =>
    is => 'rw',
    isa => 'ArrayRef[Order]',
    default => sub { [] },
    traits  => ['Array'],
    handles => {
        add_order  => 'push',
        get_orders => 'elements',
    },


no Moose;
__PACKAGE__->meta->make_immutable;

Adding an item as an order gives a nice error message:

my $fred = Person->new(name => 'fred');
my $item = Item->new(description => 'One true ring');
$fred->add_order($item);
$ perl moose-arrays.pl
A new member value for orders does not pass its type constraint because:
Validation failed for 'Order' with value Item=HASH(0x9ad3ec8)
(not isa Order) at moose-arrays.pl line 63

Moose ensures you pass an order to add_order(…).

my $order1 = Order->new(order_id => 'fred1');
my $item = Item->new(description => 'One true ring');
$order1->add_item($item);
$fred->add_order($order1);

my $order2 = Order->new(order_id => 'fred2');
$fred->add_order($order2);

use Data::Dumper;
print Dumper($fred);
$VAR1 = bless( {
                 'orders' => [
                               bless( {
                                        'order_id' => 'fred1',
                                        'items' => [
                                                     bless( {
                                                              'description' => 'One true ring'
                                                            }, 'Item' )
                                                   ]
                                      }, 'Order' ),
                               bless( {
                                        'order_id' => 'fred2',
                                        'items' => []
                                      }, 'Order' )
                             ],
                 'name' => 'fred'
               }, 'Person' );

I like it when someone else has already written the code I would otherwise need to write myself.

Plack Vs FastCGI

I’ve been sold on Plack for a while. This clarifies a part of the reason nicely1.

If you design a fibonacci() function, would you make it print the result to STDOUT, or return the result as a return value?

(It’s referring to the PSGI spec rather than Plack, but I figure the latter needs press a bit more)

Quick thought though – if a page takes a long time to generate, the stdout technique can deliver a bit at a time. Is there a plack plugin for that, or is the answer to go for ajax these day and deliver the page outline asap?


1. Namely that printing to stdout always seemed like a horrible and inefficient hack.

One thing I like about developing the emacs environment (i.e. writing emacs lisp) is programming in the image. In contrast when I run a perl script, any data loaded into the script vanishes when the script exits.

my $image = {};
populate_particular_set_of_people($image);
populate_particular_set_of_orders($image);
# ... more populate functions ...
produce_report($image);

If the populate functions take a long time to run and there is a syntax error in one of them, I might waste a lot of time waiting for data to be loaded over and over and potentially annoy my DBA.

Hence my thinking about REPLs earlier in the year.

Instead, I can mitigate this problem and support exploratory programming by serialising my data structure to disk after each section has been loaded.

use Storable;

use constant IMAGE_FILE => '/tmp/.jareds-image-RANDOMTEXT';

sub populate_particular_set_of_people
{
    my $image = shift;

    return if (exists $image->{'store'}{'people'});

    # Get the set of people

    store $image->{'store'}, IMAGE_FILE;
}

sub populate_particular_set_of_orders
{
    my $image = shift;

    return if (exists $image->{'store'}{'orders'});

    # Get the set of orders

    store $image->{'store'}, IMAGE_FILE;
}

my $image = {};
$image = retrieve(IMAGE_FILE) if -f IMAGE_FILE;

populate_particular_set_of_people($image);
populate_particular_set_of_orders($image);
# more populate functions
produce_report($image);

Error handling has been elided.

I’m only storing part of the hashref, $image->{'store'} in this example. This is fairly typical of my standard use case for this technique – quick one off reports. Some of the data is slow to load in from the database so I persist it to disk. The rest is calculated based on the loaded data so I don’t persist it. I keep all of the data together so I can pass it to each subroutine as a single parameter.

Of course, I wouldn’t recommend this technique for a production system.

Neat solution for deploying/running Perl Apps on Windows:

… [share] your production Perl installation, with all the packages required by all your apps correctly installed. And place the top-level .pl scripts (or some placeholder .cmd files if some local setup is required), within that installation. Then your users can run those applications from that shared installation.
Follow

Get every new post delivered to your Inbox.