Store a Moose object that has a PDL as an attribute
Asked Answered
A

2

7

I am new to Moose and doing quite well until I have hit a snag using a PDL as a property. I want to be able to write an object to a file (I have been using use MooseX::Storage; with Storage('io' => 'StorableFile');, and this object has a PDL as a attribute. PDL::IO::Storable provides the necessary methods to use Storable in this way, however I am at a loss as to how to do this in Moose.

Here is an example, it is a little long, I know, but it is as minimal as I can make it:

#!/usr/bin/perl

package LinearPDL;
use Moose;

use PDL::Lite;
use PDL::IO::Storable;

use MooseX::Storage; 
with Storage('io' => 'StorableFile');

has 'length' => (is => 'ro', isa => 'Num', required => 1);
has 'divisions' => (is => 'ro', isa => 'Int', required => 1);
has 'linear_pdl' => (is => 'ro', isa => 'PDL', lazy => 1, builder => '_build_pdl');

sub _build_pdl {
  my $self = shift;

  my $pdl = $self->length() / ( $self->divisions() - 1 ) * PDL::Basic::xvals($self->divisions());

  return $pdl;
}

no Moose;
__PACKAGE__->meta->make_immutable;

use strict;
use warnings;

my $linear_pdl = LinearPDL->new('length' => 5, 'divisions' => 10);
print $linear_pdl->linear_pdl;

$linear_pdl->store('file'); # blows up here!

my $loaded_lpdl = load('file');
print $loaded_lpdl->linear_pdl;

I think I may have to make a PDL type or perhaps even wrap PDL into something (using MooseX::NonMoose::InsideOut), but perhaps someone can save me from that (or point me down the right road if it is).

Agnate answered 23/5, 2011 at 19:15 Comment(0)
D
7

You don't say what actually goes wrong. At a guess you'll need to tell MooseX::Storage how to handle the PDL object using the PDL object's Storable hooks. The documentation for this feature in MooseX::Storage is very poor but MooseX::Storage::Engine has a add_custom_type_handler() method that takes a typename (PDL in your case) and a HashRef of handlers.

MooseX::Storage::Engine->add_custom_type_handler(
    'PDL' => (
        expand   => sub { my ($data) = @_;   ...  },
        collapse => sub { my ($object) = @_; ...  },
    )
);

Please swing past #moose on irc.perl.org or the Moose mailing list and ask.

[Edit: Update with an example based on the tests.]

Dygert answered 23/5, 2011 at 20:49 Comment(4)
this looks very promising, can you expand a little further? Do I create the $engine object in the class definition? What are the inputs and outputs for the expand and collapse subs? Is there somewhere where better documentation or tutorials may be found? Thanks!Agnate
Joel unfortunately this is an under-documented part of MooseX::Storage. That's why I was suggesting talking to the irc channel and/or list. I did a quick glance through the source for MooseX::Storage earlier because I knew this feature existed but could't remember how/where.Dygert
And I posted that last comment then realized I could look at the test suite and found an example of exactly what you want.Dygert
Excellent! That has definite promise! I'm marking you correct for having the knowledge. I will try to post my results as another answer for future readers for the specifics of Moose/PDL interaction.Agnate
D
1

The question by Joel and response from perigrin helped me solve a storage problem that had been sitting in the back of my mind for a while. I'm posting a working example here. It doesn't use PDL but it's related and may help someone in the future.

{
package MVR;
use Moose;
use MooseX::Storage;
use Math::Vector::Real;
use Data::Structure::Util qw (unbless);

with Storage('format' => 'JSON', 'io' => 'File');

MooseX::Storage::Engine->add_custom_type_handler(
  'Math::Vector::Real' => (
      expand    => sub {my $v   = shift; Math::Vector::Real->new(@{$v})},
      collapse  => sub {my $mvr = shift; return (unbless($mvr)) },
  )
);

has 'mvr' => (is => 'rw', isa => 'Math::Vector::Real');

1;
}

use Math::Vector::Real;
my $p = MVR->new(mvr => V(0,1,3));

print $p->dump;
$p->store('my_point.json');

my $p1 = MVR->load('my_point.json');

print $p1->dump; 
Dania answered 23/6, 2015 at 14:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.