Skip to content

Couple of CPAN pressies

December 26, 2009

Just uploaded a couple of new modules to CPAN:

The first one you is just a small xmas cracker that you will already know about from my “bare URL” post from last week. Just pull, enjoy for a little while and then chuck away like most xmas cracker toys :)

The second one is a tad similar (ie. Devel::Declare) but with a much more sympathetic syntax by allowing you to create new Quote-Like Operators in Perl with Perl.

For a good end product exemplar have a look at PerlX::QuoteOperator::URL included with the distribution:

use PerlX::QuoteOperator::URL 'qh';

my $content = qh{ http://transfixedbutnotdead.com/ };

There is no scary parsing going on with this example. PerlX::QuoteOperator / Devel::Declare simply hits the ‘qh’ keyword and converts it to:

qh qq{ http://transfixedbutnotdead.com/ }

And ‘qh’ is a subroutine with a ($) prototype. So nothing too sinister (unless you really do abhor subroutine prototypes!), just a simple macro which gives the appearance that we have new quote-like operators.

Certainly an interesting concept to be able to produce new quote-like operators in Perl. So hopefully PerlX::QuoteOperator might find its way under a few xmas trees :)

Merry Xmas & happy St. Stephen’s day to everyone.

/I3az/

PS. I chose the PerlX::* because gugod as already provided some wonderful Devel::Declare Perl extending modules under this namespace. I feel its in the same vein so hopefully a good place for it to live.

Contributing to a project on Github

December 24, 2009

After getting my head into Devel::Declare::Context::Simple to create the bare URL for my last blog post
I realised that I’ve percolated enough knowledge about the module that it would be a good idea to redirect it back to the project by at least doing the POD.

This will be the first time I’ve “properly” contributed in some form to an opensource project (“properly” being via source control management & a patch).

Devel::Declare is hosted on Github here. And the process to contribute back changes to a Github project is “forking” simple!

With Git & Github its all about forking. Here is a concise Github howto (which I’ll regurgitate below with my own slant & spiel!).

I only use Git for my Github projects, so forking etc is all new to me. To break it down into a few simple steps the process to contribute would be:

  • Fork project
  • Clone your fork
  • Make your changes
  • Push changes back to you fork
  • Send pull request back to original project

 

Here are the minutiae steps I went through for Devel::Declare:

  • Went to Devel::Declare project on Github and forked it.
  • Forked project now appears in my project list.
  • Cloned my forked Devel::Declare (use “Your Clone URL” copy/paste)
    git clone git@github.com:draegtun/devel-declare.git
    cd devel-declare/

  • Linked my forked project to original
    git remote add upstream git://github.com/rafl/devel-declare.git
    git fetch upstream

  • Make my changes to project
  • Run tests (in case I did something stupid!)
    perl Makefile.PL
    make
    make test

  • Clear down build once happy
    make realclean

  • Push my changes back to my fork
    git commit -a -m "Documentation added to D::D::Context::Simple + examples directory"
    git push origin master

Now on Github the changes can be seen in my fork

All I do now is click the “pull request” button and off went a request of my changes to rafl. Fingers cross my documentation changes were good enough to be accepted.

So I’m no longer a virgin to contributing to this opensource malarky :)

/I3az/

URL, Devel::Declare and no strings attached

December 16, 2009

This Hacker News article caught my eye yesterday which pointed to a blog post about having a raw URL within a Ruby program using some clever shenanigans. (They you go, I saved you having to click through to find all the links yourself!)

Some examples from blog post:

# display this JSON request
puts http://github.com/defunkt.json

# => "He nose the truth."
require 'json'
url = http://twitter.com/statuses/show/6592721580.json
JSON.parse(url.to_s)['text']   

Very clever indeed. Of course there will be some edge cases but it does show you how far you can stretch Ruby. NB. Didn’t work in 1.9 for me but worked with minor warning in 1.8.2 (yes I know it old but thats what shipped with Mac OSX Tiger).

So how far can we stretch Perl? Well with Devel::Declare it can be stretched all the way:

use Modern::Perl;
use JSON qw(decode_json);
use URLDSL;

# print the json
say http://twitter.com/statuses/show/6592721580.json;

# => "He nose the truth."
say decode_json( http://twitter.com/statuses/show/6592721580.json )->{text};

So Perl also has no strings attached ;-)

Devel::Declare allow us to extend the Perl syntax in a robust and easy fashion:

package URLDSL;
use Modern::Perl;
use Devel::Declare ();
use LWP::Simple ();
use base 'Devel::Declare::Context::Simple';

sub import {
    my $class  = shift;
    my $caller = caller;
    my $ctx    = __PACKAGE__->new;
    
    Devel::Declare->setup_for(
        $caller,
        { 
            http => { 
                const => sub { $ctx->parser(@_) },
            },
        },
    );
    
    no strict 'refs';
    *{$caller.'::http'} = sub ($) { LWP::Simple::get( $_[0] ) };
}

sub parser {
    my $self = shift;
    $self->init(@_);
    $self->skip_declarator;          # skip past "http"

    my $line = $self->get_linestr;   # get me current line of code
    my $pos  = $self->offset;        # position just after "http"
    my $url  = substr $line, $pos;   # url & everything after "http"
    
    for my $c (split //, $url) {
        # if blank, semicolon or closing parenthesis then no longer a URL
        last if $c eq q{ };
        last if $c eq q{;};
        last if $c eq q{)};
        $pos++;
    }    
    
    # wrap the url with http() sub and quotes
    substr( $line, $pos,          0 ) = q{")};
    substr( $line, $self->offset, 0 ) = q{("http};
    
    # pass back changes to parser
    $self->set_linestr( $line );

    return;
}

1;

 

Here is a low level synopsis of how it worked:

  • Devel::Declare tells the perl parser to call parser() when it hits http keyword
  • http://twitter.com/statuses/show/6592721580.json example triggers this (perl has no problem naturally distinguishing “http” keyword from “http://”)
  • Get line of code in question (my $line = $self->get_linestr; )
  • parser() skips along the URL data following “http” ($self->offset) until it reaches a space, semicolon or a closing bracket (this covers “most” cases though comma could be an issue). This marks the end of the URL data
  • We now in essence change http://twitter.com/statuses/show/6592721580.json into http("http://twitter.com/statuses/show/6592721580.json")
  • And plonk the changed line back to the parser ($self->set_linestr($line);) and let it continue along its merry way
  • NB. http() sub was already imported into calling space and returns a LWP::Simple::get of the requested URL

 

Now is URLDSL useful in the real world? It can screw up syntax highlighting a bit (though WordPress highlighter coped extremely well, unlike Github :(

Its robust enough to cope with normal string interpolation:

my $id = '6592721580';
say decode_json( http://twitter.com/statuses/show/$id.json )->{text};

So perhaps I should upload it to CPAN? (earmarked for ACME:: perhaps!?). Anyone think this is useful little helper module then I wrap it up the next time I get a free moment.

The exercise as been fruitful in allowing me to get my head into the amazing Devel::Declare module for the first time.

I’ve used the Devel::Declare::Context::Simple class which simplifies things. Unfortunately there isn’t a POD on this yet but the main Devel::Declare docs nicely demonstrate the correct mechanics so its easy to adapt from this.

I also found this blog post by franck cuny to be extremely helpful. As was delving through the source code of other modules that used Devel::Declare

/I3az/

Keeping to a schedule

December 13, 2009
tags:

When I made my Blogging Milestone post I decided to have a crack of writing Perl posts to a fixed schedule.

The Blogging Milestone post marked ten days since the previous post (ie. the Iron Man limit!). The following posts would continue to happen but reduced by a day each time. So next was 9 days later… then 8 days later… then 7 days later… until I reached zero days… my last post.

Phew… it did take a bit of effort to keep to a strict deadline but it is a good carrot & stick to keep you going!

Obviously I felt confident enough that I could do it (but not confident enough to announce that I was doing it!) and having lots of blog ideas written down + some partially composed ones does help ;-)

For all those posters that are doing Perl advent calendars at the moment I know what you must be going through and my hats off to you all.

/I3az/

to DO or not to DO, that is the question

December 6, 2009
tags:

Following on from yesterdays post about do blocks, this is what I would normally do off the bat:

sub word_freq {
    my %words;
    $words{$_}++ for split /\s+/, lc $_[0];
    \%words;
}

Returning back a hash reference is both leaner and meaner ;-)

use List::Util qw(sum);

my $s = "The green hat is tHe twin of the green hat";

my $num_of_hats = word_freq( $s )->{ hat };   # word count just for 'hat'

# don't worry... always unique hashrefs returned:
my $hash_ref    = word_freq( $s );
my $hash_ref2   = word_freq( $s );       

# thus you can safely:
$hash_ref2->{green} = 100;
say "$hash_ref->{green} : $hash_ref2->{green}"; # => "2 : 100"    

# clean copy for those who prefer there hashes not to be hashrefs!
my %hash = %{ word_freq( $s ) };       

# returns ( 'is', 'of')
my @two_letter_words  = grep { length $_ == 2 } keys %{ word_freq( $s ) };

# number of "green" + "hat" == 4
my $green_plus_hat = sum @{ word_freq( $s ) }{ qw/green hat/ };

 

And what I probably wouldn’t do is:

use List::MoreUtils qw(uniq);

my $s = "The green hat is tHe twin of the green hat";

my %words = do {
    my @words = split /\s+/, lc $s;
    map { 
        my $word = $_; 
        $word => scalar grep { $_ eq $word } @words;
    } uniq @words
};

I actually prefer the code aesthetics of this but the extra cycle (grep) through @words pushes me towards the leaner hash counting solution. Horses for courses? ;-)

/I3az/

Anything you can DO I can DO better

December 5, 2009
tags: ,

Here is a simple world count in Ruby from recent post at Refactormycode.com:

s = "The green hat is the twin of the green hat"
h = Hash.new(0)
s.split.each do |w|
  h[w.downcase] += 1
end

If you know Ruby then you know this isn’t very idiomatic. Here is something closer to would normally see in Ruby world:

h = s.downcase.split.inject(Hash.new(0)) { |h,k| h[k] += 1; h }

But the style of the original code is something I’ve seen often in Perl:

my $s = "The green hat is tHe twin of the green hat";
my %h; 
for my $w (split /\s+/, $s) {
    $h{ lc $w }++;
}

Now if brevity was key to better code then you could do this:

my %h; $h{$_}++  for split /\s+/, lc $s;

But I think its better to do something like this:

my %words = do { 
    my %h;
    $h{$_}++  for split /\s+/, lc $s;
    %h;
};

OK this is not a great example of do blocks and isn’t even as DRY compared to original code. But I do find this more aesthetic IMHO.

Perhaps a better example of what do blocks can do is to produce another naff example!

my $num_string = do {
    my $num = get_random_num_between_1_and_3();
    if    ($num == 1) { 'one' }
    elsif ($num == 2) { 'two' }
    elsif ($num == 3) { 'three' }
};

do blocks return the last evaluated result. And result can be plural:

my $year = get_year();
my ($champions, $runners_up) = do {
    if    ($year == 2003) { ('England', 'Australia')    }    
    elsif ($year == 2007) { ('South Africa', 'England') }
};

say "Rugby World champions for $year: $champions  Runners up: $runners_up";

So do blocks are useful tools in helping to make code more focused and avoid unnecessary pollution of variables into calling namespace.

But we can either move up another notch by using anonymous subroutines:

my ($champions, $runners_up) = sub {
    given ($_[0]) {
        when (2003) { return ('England', 'Australia')    }
        when (2007) { return ('South Africa', 'England') }
    }
}->( get_year() );

This anon sub block is built and then immediately executed by the ->() bit.

So works much like a do block except we can short circuit flow with return thus enabling us more freedom and control over what these blocks of code can do.

Using do / anon sub blocks is something that Perl can definitely learn from Ruby. Here is another recent example of do usage that I like a lot (see has).

NB. Another advantage of the do / anon sub block approach is that at anytime the block gets big or its needed elsewhere then it doesn’t take much to turn it into a proper subroutine.

 

I’ll end with my obligatory autobox solution of the original code:

my $s = "The green hat is tHe twin of the green hat";

my %words = $s->lc->split( qr{\s+} )->hash_count->flatten;

sub autobox::Core::ARRAY::hash_count {
    my $list = shift;
    my %h;
    $h{$_}++ for @$list;
    \%h;
}

You can even do:

'The green hat is the twin of the green hat'->lc->split( qr{\s+} )->hash_count->flatten;

But I can’t think where something like this would ever be useful in the real world? Though it is nice to look at when running it via the extremely useful Devel::REPL ;-)

/I3az/

Github and POD

December 3, 2009
tags: , ,

If you look at the Github README formatting guide you will notice a feature request for POD that yours truly left there 10 months ago.

Recently I noticed that POD’s on Github were being rendered now (which may have been the case for quite a while and simply passed me by!). For eg. chromatic’s Modern Perl Book outline.pod.

So I added a README.pod to my Builder repo on Github and it works taking precedence over the plain README when rendering the repo landing page.

So no need to resort to using Markdown or Textile… its POD all the way! Hats off to Github for adding POD.

This is the README.pod I ended up with after a few trial attempts:

=head1 Builder

Build XML, HTML and (eventually!) other outputs in blocks
 

=head2 VERSION

version 0.04

This distribution includes the following modules:

    Builder             (0.04)
    Builder::Utils      (0.02)
    Builder::XML        (0.02)
    Builder::XML::Utils (0.02)
    

=head2 SYNOPSIS

Using building blocks to render XML, CSS, HTML and other outputs.

    use Builder;
    my $builder = Builder->new;
    my $xm      = $builder->block( 'Builder::XML' );
    
    
    # example 1
     
    $xm->parent( { isa => 'Mother' }, $xm->child( 'Hi Mum!' ) );
    say $builder->render;
    
    # <parent isa="Mother"><child>Hi Mum!</child></parent>
    
    
    # example 2
     
    $xm->parent( sub {
        for my $say qw/Mum Dad/ {
            $xm->child( "Hi $say" );
        }
    });
    
    say $builder->render;
        
    # <parent><child>Hi Mum</child><child>Hi Dad</child></parent>


=head2 INSTALLATION

To install this module, run the following commands:

	perl Build.PL
	./Build
	./Build test
	./Build install


=head2 DEPENDENCIES

This module requires these other modules and libraries:

	Carp


=head2 SUPPORT AND DOCUMENTATION

After installing, you can find documentation for this module with the
perldoc command.

    perldoc Builder


=head2 COPYRIGHT AND LICENCE

Copyright (C) 2008,2009 Barry Walsh (Draegtun Systems Ltd)

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

/I3az/

Update 08-Dec-2009: I’ve now amended the GitHub README formatting guide wiki to show that POD is now a supported format

Follow

Get every new post delivered to your Inbox.