Sunday, 29 May 2011

In which Alex learns Moose

Today I have decided to learn Moose.  I shall do this by converting my spider-web latex generation master script, now existing in four different incarnations, into an application class.  It will be easy! Or will it?  I liveblog myself, thus:

15:00 Finally decide to be productive (it is Sunday).
15:01 Decide to re-write generate.pl
15:02 type 'perl -MCPAN -e shell' 'install MooseX::Getopt'
15:12 While waiting for Moose to install, decide to liveblog myself.  The install is taking a whole long while...
15:16 Meanwhile, I have written this, which I hope will work:

package MyApp::Generate;
use Moose;
with 'MooseX::Getopt';

has small => (is => 'rw', isa => 'Int', default => 0);

1;

15:23 Still waiting for Moose to build and test and install. I'd like to at least run perl -c on my snippet to see if I'm a fool or not, but as yet, I'm ignorant even of my foolishness.

15:29 Oh, there we are, installed. Time to try the very basic:

use 5.12.0;
use lib "$ENV{HOME}/alexwork/perl/";
use MyApp::Generate;

my $app = MyApp::Generate->new_from_opts();

15:33 Well, that works at least. Now, to make things work. (This might take a while).
15:38 So, I want a list of somethings, but not have it be commandline-able, this can be done using an attribute with a leading underscore:

has '_lib' => (accessor => 'lib', isa => 'ArrayRef[Str]', default => ['lib']);

15:47 Well, that didn't work, an enormous error (can I stop these enormous traces?) tells me I can't have a reference as a default, but I can have a sub to wrap it, so I do that.
16:12 Importing the crufty methods and changing the million script-local my variables into attributes of the class. How do I get a the entries of a HashRef attribute?
16:15 By which I mean, get in a tidy manner. For now I'll just grab it and use it.
16:28 still bashing in methods. Wondering what the output of an 'ArrayRef' attribute will be, a list or a reference. Not immediately clear.
16:35 well, it runs, but I want to have my options just as '--nopdf'. Maybe I can't do this, that would be sad.
16:39 Ah, I need to make the attributes be 'Bool' then MooseX::Getopt figures it out fine. Not all sad, happy even.
16:41 Now having trouble with a builder method. It's getting called, I'm going to find out what with.
16:45 As expected, I'm now in a confused state where I'm not quite sure why this method is being called.
16:46 so it looks like it's being called as part of the ->new_with_options during object construction, so maybe the builder is called when a default value is created...
16:48 Yes, this is so. I've added a guard for the default case.
16:50 I've constructed my object, now I fail to access an ArrayRef attribute correctly. What should it be?
16:51 It is indeed an array reference.
16:53 Now it seems I don't understand what a builder is for. Perhaps I really just need to write my own set_foo which then sets other things (I have an option which sets lots of things).
17:03 Well, I didn't. A builder is a different way to set a default, but to be able to override this in subclasses. I really want a trigger which will then go and set the other attributes.
17:06 Hmm, I can't suggest a trigger to be a method. For now this isn't a problem.

has src => (is => 'rw', isa => 'Str', default => '', trigger => \&_src_set);
sub _src_set {
    my $self = shift;
    my $val = shift;
    return unless defined($val);
    $val =~ s/\.tex$//;
    $self->out($val);
}

17:14 This now works for the first script, let's see if I can impose the class on the other generation routines without too much crying...
17:25 Different journals have their quirks, so it's time for a subclass instead of a slightly different but otherwise the same script.
17:35 Well, that was nice and easy.

Moral of the story: That was really very easy.

Next is to use more than just Moose. I think I like MooseX::Method::Signatures; One trouble, with picking all this up, it's that it's not clear what's worth picking up.

No comments:

Post a Comment